Blogger Information
Blog 49
fans 0
comment 0
visits 38388
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
初识JS变量与常量、函数、作用域与闭包、模板字符串与标签函数
超超多喝水
Original
607 people have browsed it

初识 JS 变量与常量、函数、作用域与闭包、模板字符串与标签函数

变量与常量

变量

所谓变量,简单来说就是一个可变的量,一个变量通常由三部分组成:

  1. 变量声明
    变量使用 let 关键字来声明,需要注意,let 禁止重复声明,同一个作用域内,变量的名称是唯一值,否则控制台会报错提示该变量已被声明(var 由于没有作用域限制,不建议使用)

  2. 变量名称(标识符)
    标识符命名规则
    1、必须使用英文字母、数字、下划线”_“、$,只允许用这四种来命名
    2、变量名可以使用中文,但是一般不推荐使用
    3、变量名的开头不允许是数字
    标识符命名风格
    1、蛇形:USERNAME,多个单词之间用下划线”\“连接,一般用于常量
    2、驼峰:userName getUserName,第二个单词起首字母大写,一般用于变量跟函数
    3、大驼峰:UserName,也叫帕斯卡命名,一般用在类/构造函数中

  3. 变量的值
    1、变量的声明是可以不赋值的,不赋值的时候默认为 undefined,即:

    1. let num;

    2、第一次赋值也叫初始化,即给变量初始化一个赋值

    1. num = 60;

    3、第二次及以后重新给变量赋值,即变量值的更新或修改

    1. num = 80;

    4、变量值的清除

    1. num = null;

一般写的时候可以将声明与初始化合二为一,即:

  1. let num = 60;

常量

常量的要求及规范与变量基本相同,需要注意以下几点:

  1. 常量声明使用关键字”const”
  2. 常量在代码执行期不允许更新数据
  3. 声明时必须赋值
  4. 常量也是一种特殊的变量,名称除在常量中唯一外也不能与变量的名称相同
  5. 在代码中首选常量,除非确定该数据会发生变化
  1. const USER_NAME = "admin";

数据类型

只有相同数据类型之间,他们的运算才具有意义,如数值加数值,会计算两个数之和,字符串加字符串会将两个字符串进行拼接等

  • 例:100+100 运算
  1. console.log(100 + 100);

100+100

  • 例:“100”+”100” 运算
  1. console.log("100" + "100");

"100"+"100"

原始类型

原始类型分为以下五种:

  • 数值(number)
  1. // 整数
  2. console.log(typeof 100);
  3. // 小数
  4. console.log(typeof 100.1);

number

  • 字符串(string)
  1. console.log(typeof ("100" + "years old"));

string

  • 布尔值(boolean)
  1. // true
  2. console.log(typeof true);
  3. // false
  4. console.log(typeof false);

boolean

以上三种最为常用,还有两个特殊值

  • 未定义数值(undefined)
    一般变量只声明未赋值时,默认是 undefined 类型
  1. let a;
  2. console.log(typeof a);

undefined

  • 空对象(null)
    当一个变量需要清空数据内容时,可以赋值一个 null,但是这里会返回一个空的对象类型(object),而不是 null 类型(没有 null 类型)
  1. let a = null;
  2. console.log(typeof a);

null

引用类型

引用类型分为以下 3 种:

  • 数组
    1. 数组的变量是一个相关数据的引用的集合
    2. 可以通过变量名+成员的索引访问这个集合中的任何一个成员
    3. 成员的索引默认从 0 开始
    4. 数组的集合内可以有一个值,也可以有多个值
    5. 数组的集合内的成员可以是任意类型

如:

  1. let arr = [
  2. 123,
  3. "admin",
  4. null,
  5. true,
  6. undefined,
  7. [10001, 10002, 10003],
  8. { uname: "admin", pwd: "123456" },
  9. function sum(a, b) {
  10. return a + b;
  11. },
  12. ];
  13. console.log(arr);
  14. console.log(arr[0]);
  15. console.log(arr[2]);

数组

  • 对象
    对象与数组类似,需要注意以下几点:

    1. 数组的索引是从 0 开始的正整数,对象的索引是自定义的字符串或标识符
    2. 变量在对象中叫属性
    3. 变量引用时用点语法arr.uname
    4. 当属性使用了非法标识符时,必须转为字符串(加入空格等)
    5. 当索引是字符串时,用[]直接调用arr["my pwd"]
    6. 对象的简写(一):属性的简写,当一个变量与对象的作用域相同名称也相同(变量名与对象属性相同)时,可以简写
    7. 对象的简写(二):方法的简写,方法就是属性的值是一个函数,方法的简化就是将”:function”去掉
    8. 在对象中可以使用 this 变量与当前对象绑定
    9. 使用 this 变量的时候需要注意,对象的方法不能使用箭头函数,因为箭头函数的 this 是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象
      如:
  1. let arr = { uname: "admin", "my pwd": 123456 };
  2. console.log("1:");
  3. console.log(arr);
  4. console.log("2:" + arr.uname);
  5. console.log("3:" + arr["my pwd"]);
  6. console.log("---------");
  7. // 对象的简写
  8. // 属性的简化
  9. let uname = "admin";
  10. let info = {
  11. uname: "admin",
  12. };
  13. console.log("4:" + info.uname);
  14. console.log("---------");
  15. // 以上可以简写为uname: uname,
  16. info = {
  17. uname: uname,
  18. };
  19. console.log("5:" + info.uname);
  20. console.log("---------");
  21. // 或者可以进一步简写为uname,
  22. info = {
  23. uname,
  24. };
  25. console.log("6:" + info.uname);
  26. console.log("---------");
  27. // 方法的简化
  28. info = {
  29. uname,
  30. getInfo: function () {
  31. return "欢迎:" + info.uname;
  32. },
  33. };
  34. console.log("7:" + info.getInfo());
  35. console.log("---------");
  36. // 以上可以简写可以去掉: function()
  37. info = {
  38. uname,
  39. getInfo() {
  40. return "欢迎:" + info.uname;
  41. },
  42. };
  43. console.log("8:" + info.getInfo());
  44. console.log("---------");
  45. // this
  46. //此时this指向的就是info1
  47. info1 = {
  48. uname,
  49. getInfo() {
  50. return "欢迎:" + this.uname;
  51. },
  52. };
  53. console.log("9:" + info1.getInfo());
  54. console.log("---------");
  55. //此时this指向的就是info2
  56. info2 = {
  57. uname,
  58. getInfo() {
  59. return "欢迎:" + this.uname;
  60. },
  61. };
  62. console.log("10:" + info2.getInfo());
  63. console.log("---------");
  64. //此时在箭头函数中使用了this,发现出来的内容是undefined,因为此时this指向了window
  65. info3 = {
  66. uname,
  67. getInfo: () => "欢迎:" + this.uname,
  68. };
  69. console.log("11:" + info3.getInfo());
  70. console.log("---------");
  71. info4 = {
  72. uname,
  73. getInfo: () => "本页面地址" + this.location,
  74. };
  75. console.log("12:window对象的location属性:" + info4.getInfo());
  76. console.log("---------");

对象

  • 函数

    1. 函数是由 function+函数名(可选)+括号+括号里面的参数(可选)+大括号+大括号里面的内容{可选}组成的,如:function getTotal(a,b){return a + b;}
    2. 函数名推荐使用动词加名称的写法
    3. 函数声明的时候函数名后面括号里的内容叫形参(形式参数)
    4. getTOtal(10,20):调用函数是函数名+括号来调用,如果里面有参数,括号内可以传参
    5. 函数调用时传入的参数叫实参(实际参数)
    6. console.dir(getTotal);:函数也是对象,也有属性跟方法,使用console.dir()可以输出函数详情
    7. function getTotal(a,b=10){return a + b;}:当传入的参数可能不足时,可以设置默认参数来解决
    8. function getTotal(...args){}:当传入的参数过剩时,可以使用 rest 参数来解决,rest 参数会将所有参数压到一个数组中
    9. getTotal(...args):关于…:…用在函数的形参中,就是 rest,归并,用在函数的调用中就是扩展(展开)
    10. 匿名函数(一):(function (a,b){return a + b;})(10,20):所谓匿名函数就是没有名称的函数,第一种匿名函数是一次性,立即调用的函数,由(匿名函数)+(参数组成)
    11. 匿名函数(二):let add = function (a,b){return a + b;}如果该匿名函数不是一次性的,应该使用函数表达式将匿名函数赋值给一个变量
    12. 箭头函数(一):let add = (a,b) => {return a + b;}:箭头函数可以简化匿名函数表达式,可以将 function 去掉直接用=>将形参跟函数内容连在一起
    13. 箭头函数(二):let add = (a,b) => a + b:如果函数的内容只有一行代码,则大括号、大括号里面的 return、大括号里面最后的;都可以省略
    14. 箭头函数(三):let add = a => a + b如果形参也只有一个,那么形参的括号也可以省略
    15. 箭头函数(四):let add = () => a + b需要特别注意如果没有形参,那么形参这里的括号一定不能省略
      匿名函数开始的代码还没写

示例:

  1. function getTotal(a, b) {
  2. return a + b;
  3. }
  4. console.log(getTotal(10, 20));
  5. console.dir(getTotal);
  6. console.log(getTotal.name);
  7. console.log(getTotal.length);

函数示例1

  1. const arr = [10, 20, 30, 40, 50, 60, 70, 80, 90];
  2. console.log(arr);
  3. console.log(...arr);
  4. function getTotal(...args) {
  5. return args.reduce((p, c) => p + c);
  6. }
  7. console.log(getTotal(...arr));

函数示例2

  1. // 匿名函数
  2. // 立即调用函数。IIFE
  3. console.log(
  4. (function (a, b) {
  5. return a + b;
  6. })(10, 20)
  7. );
  8. console.log("---------");
  9. // 函数表达式
  10. let add = function (a, b) {
  11. return a + b;
  12. };
  13. console.log(add(20, 30));
  14. console.log("---------");
  15. // 箭头函数
  16. // 常规简化
  17. add = (a, b) => {
  18. return a + b;
  19. };
  20. console.log(add(30, 40));
  21. console.log("---------");
  22. // 函数代码只有一行简化
  23. add = (a, b) => a + b;
  24. console.log(add(40, 50));
  25. console.log("---------");
  26. // 形参只有一个简化
  27. add = a => a + a;
  28. console.log(add(60));
  29. console.log("---------");
  30. // 无形参时简化
  31. add = () => "hello world";
  32. console.log(add());

匿名函数

作用域与闭包

作用域

  • 全局作用域:在函数外面的作用域是全局作用域,全局作用域声明的变量可全局访问
  • 函数作用域:函数内部的作用域,函数作用域的变量无法在函数之外访问
  • 块作用域:用一个大括号包起来的作用域叫块作用域,类似于函数作用域
  • 函数内部查询变量,先在函数作用域内查询,如果函数作用域内没有,就往上一级一级找,直到找到全局作用域,这个查询的链路也叫作用域链
  • 作用域的内容单向传递,即只能由上一级作用域向下一级传递,不能从下一级往上一级传递
  1. // 全局作用域
  2. let a = 100;
  3. let d = 200;
  4. // 块作用域
  5. {
  6. let b = 300;
  7. let d = 400;
  8. let e = 700;
  9. // 函数作用域
  10. function getTotal() {
  11. let c = 500;
  12. let d = 600;
  13. // 查询a时,沿着作用域链,先找当前级别是否有a,没有继续往上找,直到找到全局作用域
  14. // 查询b时,也是沿着作用域链查找,在块作用域中找到b
  15. // 查询c时,在本级查到,直接使用
  16. // 查询d时,也是在本级查到,直接使用,不再往上去找块作用域跟全局作用域的d
  17. return a + b + c + d;
  18. }
  19. }
  20. // 最后结果应该是全局作用域的a+块作用域的b+函数作用域的c跟d,即100+300+500+600=1500
  21. console.log(getTotal());

作用域

闭包

一个闭包函数,需要同时具备两个条件一个是有一个父函数,且下面必须还存在一个子函数,且存在子函数的自由变量

  1. // 父函数
  2. function parent(n) {
  3. // 子函数
  4. function son(m) {
  5. let v = 100;
  6. // n:子函数son的自由变量
  7. // m:子函数son的外部参数,属于子函数son的自有变量
  8. // v:子函数son的私有参数,属于子函数son的自有变量
  9. return n + m + v;
  10. }
  11. // 外部调用parent会返回son函数
  12. return son;
  13. }
  14. // 外部调用parent会返回son函数
  15. console.log(parent(200));
  16. console.log("---------");
  17. // 外部调用parent后再调用son才能返回最终结果
  18. console.log(parent(200)(300));

闭包

结合 IIFE 立即执行函数,实现点击量增加及添加一个基础浏览量的小案例

  1. let count = (function (n) {
  2. return function () {
  3. return n++;
  4. };
  5. })(10000);
  6. // 以上代码可用箭头函数简写为:
  7. // let count = (n => () => n++ )(10000);
  8. console.log(count());
  9. console.log(count());
  10. console.log(count());
  11. console.log(count());
  12. console.log(count());
  13. console.log(count());
  14. console.log(count());

闭包小案例

模板字符串与标签函数

模板字符串

传统字符串多行和表达式的混写非常麻烦,使用 es6 的模板字符串可以解决该问题。

  1. 模板字符串使用反引号声明不用引号
  2. 书写多行内容遇到换行时,直接在反引号内换行即可,但是需要注意第一个换行有可能默认不会顶格,需要手动删除空格
  3. 使用${…}插值占位符,可以将变量或者表达式嵌入到字符串中
  1. // 普通变量声明
  2. let strN = "普通变量声明";
  3. console.log(strN);
  4. // 模板字符串变量声明
  5. let strT = `模板字符串变量声明`;
  6. console.log(strT);
  7. // 普通变量换行操作
  8. strN = "普通变量\n换行操作";
  9. console.log(strN);
  10. // 模板字符串变量换行操作
  11. strT = `模板字符串变量
  12. 换行操作`;
  13. console.log(strT);
  14. // 普通变量拼接运算操作
  15. const a = 10;
  16. const b = 20;
  17. let addN = a + "+" + b + "=" + (a + b);
  18. console.log("普通变量拼接运算操作" + addN);
  19. // 模板字符串变量拼接运算操作
  20. const c = 30;
  21. const d = 40;
  22. let addT = `${c}+${d}=${c + d}`;
  23. console.log("模板字符串变量拼接运算操作" + addT);

标签函数

使用模板字符串作为参数的函数就叫做标签函数。
标签函数注意:

  1. alert console.log 等可以直接跟模板字符串来输出内容,而不用加括号
  2. alert 不能直接输出变量,但是 console.log 可以
  3. 标签函数第一个参数是字符串中字面量组成的数组,从第二个参数起是插值表达式
  4. 标签函数同样支持 rest 参数
  1. // alert+模板字符串直接输出
  2. // alert`alert+模板字符串直接输出`;
  3. // console.log()+模板字符串直接输出
  4. console.log`console.log()+模板字符串直接输出`;
  5. // alert+带变量的模板字符串直接输出
  6. const a = 10;
  7. // alert`alert+带变量的模板字符串直接输出:${a}`;
  8. // console.log()+带变量的模板字符串直接输出
  9. console.log`console.log()+带变量的模板字符串直接输出:${a}`;
  10. // 标签函数第一个参数是字符串中字面量组成的数组,从第二个参数起是插值表达式
  11. function getTotal(strings, num1, num2) {
  12. return `今日进货总数为:${num1 + num2}件`;
  13. }
  14. console.log(getTotal`今日进货情况:小王进货${100}件,小张进货${149}件`);
  15. //使用rest参数对不定数量的多个值进行操作
  16. function add(strings, ...args) {
  17. let sum = `${args.join("+")}=${args.reduce((p, c) => p + c)}`;
  18. return sum;
  19. }
  20. console.log(add`我想计算:${10}${20}${30}${40}${50}${60}${70}${80}${90}之和`);

alert1
alert2
clg

Correcting teacher:PHPzPHPz

Correction status:qualified

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post