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

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

超超多喝水
超超多喝水原创
2021年10月04日 16:26:16606浏览

初识 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

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议