函数的 name 属性

函数的name属性,返回该函数的函数名。

  1. var f = function () {};
  2. // ES5 之前返回的是一个空的字符串
  3. console.log(f.name); // f

每次声明一个function的时候相当于new Function进行一次实例化。
Function构造函数返回的函数实例,name属性的值为anonymous

  1. console.log(Function); // ƒ Function() { [native code] }
  2. var test = new Function();
  3. console.log(test.name); // anonymous

bind返回的函数,name属性值会加上bound前缀。

  1. function foo() {};
  2. console.log(foo.bind({}).name); // bound foo
  3. console.log(foo.call({}).name); // Cannot read properties of undefined (reading 'name')
  4. // call 相当于函数执行后没有返回值,所以报错

函数默认值

ES5中如果我们想要给一个函数的形参设置默认值改怎么做呢?

  1. function foo(x, y) {
  2. x = x || 1;
  3. y = y || 2;
  4. console.log(x + y); // 6
  5. }
  6. foo(4);

ES6简化了函数默认值的写法:

  1. function foo(x = 1, y = 2) {
  2. console.log(x + y); // 4
  3. }
  4. foo(4);

使用let声明的变量不能和函数的形参同名:

  1. let x = 1;
  2. function foo(x = 2) {
  3. let x = 2; // Identifier 'x' has already been declared
  4. console.log(x);
  5. }
  6. foo();

数组解构赋值

ES5假如我们想要连续声明多个变量需要这么写:

  1. let a = 1,
  2. b= 2,
  3. c = 3;
  4. console.log(a, b, c); // 1 2 3

ES6新增了解构的方式进行声明变量,这有点类似按照对应的下标从数组中拿数据:

  1. let [a, b, c] = [1, 2, 3];
  2. console.log(a, b, c); // 1 2 3
  3. // 解构的值会受数组顺序的影响
  4. let [b, a, c] = [1, 2, 3];
  5. console.log(a, b, c); // 2 1 3

需要注意的是等号的两边数据结构必须一致:

  1. let [d, [e], [f]] = [1, [2], [3]];
  2. console.log(d, e, f); // 1 2 3

解构失败的值会返回undefind:

  1. let [d, [e], [f]] = [1, [2], []];
  2. console.log(d, e, f); // 1 2 undefind

如果解构的参数比实际的实际少也是正常执行的,这样的情况称为「不完全结构」:

  1. let [, [e], [f]] = [1, [2], [3]];
  2. console.log(e, f); // 2 3

解构赋值还可以设置默认值,利用=表示设置为一个默认值,这和函数的默认值有点像:

  1. let [d, [e], [f = 6]] = [1, [2], []];
  2. console.log(d, e, f); // 1 2 6

默认值还可以是一个函数:

  1. function foo() {
  2. return "foo";
  3. }
  4. let [a = foo()] = [, 1];
  5. console.log(a); // 'foo'

解构赋值存在隐式转换的过程:

  1. const [a, b, c, d, e] = "hello";
  2. console.log(a, b, c, d, e); // h e l l o
  3. const { length: len } = "hello";
  4. console.log(len); // 5
  5. const { toString: s } = 123;
  6. console.log(s); // function

⚠️ 注意:除了**undefind**其他类型的**false**值都将被正常获取:

  1. let [a, b = 2, c = 3, d = 4] = [1, undefined, null, false];
  2. console.log(a, b, c, d); // 1 2 null false

解构赋值也存在暂时性死区:

  1. // 在定义 y 之前无法访问 y
  2. let [x = y, y = 1] = []; // Cannot access 'y' before initialization
  3. console.log(x, y);
  4. // 在 x 之后访问 x 这样是容许的
  5. let [x = 1, y = x] = [];
  6. console.log(x, y); // 1 1

不能重复声明:

  1. let x = 5;
  2. // 不能重复声明 x
  3. let [x = 1, y = x] = []; // Identifier 'x' has already been declared
  4. console.log(x, y);

对象解构赋值

以上是数组的解构赋值,在ES6中针对对象的语法也有一些新增。

当对象的属性名和外部变量同名时可以进行简写,函数也可以简写:

  1. // ES5
  2. var name = "张三";
  3. let sex = "male";
  4. var person = {
  5. name: name,
  6. sex: sex,
  7. age: 20,
  8. eat: function() {
  9. console.log("吃饭");
  10. },
  11. };
  12. // ES6
  13. var name = "张三";
  14. let sex = "male";
  15. var person = {
  16. name,
  17. sex,
  18. age: 20,
  19. eat() {
  20. console.log("吃饭");
  21. },
  22. };

ES6容许对象的属性名是一个动态的:

  1. let firstName = "zhang";
  2. let secondName = "san";
  3. let person = {
  4. [firstName + secondName]: "zhangsan",
  5. };
  6. console.log(person); // {zhangsan: zhangsan}

接下来看看对象的结构赋值。
对象的解构赋值同样需要遵循=两边数据结构一致的行为:

  1. let { a1: a, b: b, c: c } = { a1: 1, b: 2, c: 3 };
  2. console.log(a, b, c); // 1 2 3

以上代码可以看到**:**前面才是需要解构的参数名,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者!!!
:后面相当于是对象的属性重命名。

当定义的变量和属性名同名的时候一样可以进行简化:

  1. let { a, b, c } = { a: 1, b: 2, c: 3 };
  2. console.log(a, b, c); // 1 2 3

对象解构赋值也可以设置默认值:

  1. let { a = "a", b, c } = { b: 2, c: 3, e: 4, f: 5 };
  2. console.log(a, b, c); // 'a' 2 3

解构失败的值会返回undefind:

  1. let { a, b, c } = { b: 2, c: 3, e: 4, f: 5 };
  2. console.log(a, b, c); // undefined 2 3

同样也会出现「不完全解构」的行为:

  1. let { a, b, c } = { a: 1, b: 2, c: 3, e: 4, f: 5 };
  2. console.log(a, b, c); // 1 2 3

和数组解构赋值不同的是,对象解构赋值不存在顺序取值的问题,只要属性名和变量名一致就行:

  1. let { a, b, c } = { b: 2, a: 1, c: 3 };
  2. console.log(a, b, c); // 1 2 3

对象如何进行多层解构赋值呢?

  1. let person = {
  2. name: "张三",
  3. age: 40,
  4. son: {
  5. name: "张四",
  6. age: 30,
  7. son: {
  8. name: "张五",
  9. age: 20,
  10. },
  11. },
  12. };
  13. let { son: { son: son1 } } = person;
  14. console.log(son1); // {name: "张五", age: 20}