• 【JavaScript进阶之旅 ES6篇 第八章】函数名/对象拓展、描述符、getter/setter


    一、函数名

    1、函数表达式

    var f = function() {}
    
    // ES5及以前:函数名为 ""
    
    // ES6以后:函数名为 函数名.name
    console.log(f.name); // f
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2、Function构造函数

    1. new Function().name; // ‘anonymous’ 匿名的
    2. (new Function).name; // ‘anonymous’ 匿名的

    3、bind|call|apply绑定的函数

    ● bind 绑定的函数的name为 bound foo

    function foo() {}
    
    console.log(foo.bind({}).name); // bound foo
    // console.log(foo.call({}).name); // 报错
    // console.log(foo.apply({}).name); // 报错
    
    • 1
    • 2
    • 3
    • 4
    • 5

    二、对象的拓展

    1、对象的简写

    const foo = "bar";
    const bar = { foo };
    
    console.log(bar); // { foo: 'bar' }
    
    • 1
    • 2
    • 3
    • 4

    2、箭头函数返回对象的简写

    let foo = (a = 1, b = 2) => ({
      a, b
    });
    console.log(foo()); // {a: 1, b: 2}
    
    • 1
    • 2
    • 3
    • 4

    3、对象中函数的写法

    let age = 12;
    const p = {
      age,
      say() {
        console.log(this.age);
      }
    }
    console.log(p.age);
    p.say();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    4、CommonJS规范:module.exports跟require导出导入文件

    // index.js
    let a = 1;
    
    function foo() {
      console.log('foo');
    }
    
    function bar() {
      console.log('bar');
    }
    
    const obj = {
      a,
      foo,
      bar
    }
    
    module.exports.obj = obj;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    // main.js
    const {
      a,
      foo,
      bar
    } = require('./index.js').obj;
    
    console.log(a, foo, bar); // 1 [Function: foo] [Function: bar]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    5、属性他都要经过包装,变成一个字符串

    const arr = [1, 2, 3];
    console.log(arr[1]); // 2
    console.log(arr['1']); // 2
    
    • 1
    • 2
    • 3

    6、对象属性值的拼接覆盖

    const obj = {}
    
    obj.foo = true;
    console.log(obj); // {obj: true}
    
    obj['f' + 'oo'] = false;
    console.log(obj); // {obj: false}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    7、对象属性名拼接覆盖值(是先覆盖后找值,不会先找值)

    let a = 'hello',
        b = 'world';
    
    const obj = {
      [a + b]: true
    }
    console.log(obj); // {helloworld: true}
    
    const obj = {
      ['hello' + b]: 123
    }
    console.log(obj); // {helloworld: 123}
    
    const obj = {
      ['hello' + 'world']: undefined
    }
    console.log(obj); // {helloworld: undefined}  注意这里是undefined
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    8、属性为对象的时候,是如何将其转换为字符串的

    var obj = {};
    
    obj[true] = 'foo';
    obj[3] = 'bar';
    obj[obj] = 'baz';
    
    console.log(obj['true']); // foo
    console.log(obj['3']); // bar
    console.log(obj[obj]); // baz
    
    console.log(obj['obj']); // undefined
    
    console.log(obj['[object Object]']); // baz
    
    console.log(Boolean.prototype.toString.call(true)); // true
    console.log(Number.prototype.toString.call(12)); // 12
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    9、对象中属性的隐式转换

    const a = {a : 1},
          b = {b : 2};
    
    const obj = {
      [a]: 'a',
      [b]: 'b'
    }
    
    console.log(obj); // {'[object Object]': 'b'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    10、对象中的方法名

    const p = {
      sayName() {}
    }
    
    console.log(p.sayName.name); // sayName
    
    • 1
    • 2
    • 3
    • 4
    • 5

    三、描述符

    ● ES5之前并没有提供检测属性的方法
    ● ES5之后提供了一个属性描述符

    1、Object.getOwnPropertyDescriptor:获取对象的描述符

    ● 该方法getOwnPropertyDescriptor是存在于Object的构造器上
    ● 作用:获取对象的描述符

    const obj = {
      a: 1
    };
    
    console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
    // {
    //   configurable: true
    //   enumerable: true
    //   value: 1
    //   writable: true
    // }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    ● configurable: true 可配置的,默认是true
    ● enumerable: true 可枚举的,默认是true
    ● value: 1 值
    ● writable: true 可写的,默认是true

    2、Object.defineProperty:定义对象的属性

    const obj = {};
    
    Object.defineProperty(obj, 'a', {
      configurable: true,
      enumerable: true,
      value: 2,
      writable: false 
    });
    
    obj.a = 333; // 在非严格模式下,静默失败;在严格模式下,他会报错
    
    console.log(obj); // {a: 2}
    
    delete obj.a; // 注意:这里已经不可写了,但是可以删除
    console.log(obj); // {}
    
    
    // 变成不可删除:`configurable: false`,此时就不可以删除
    
    
    // console.log(Object.getOwnPropertyDescriptor(obj, 'a'));
    // {
    //   configurable: true
    //   enumerable: true
    //   value: 1
    //   writable: false
    // }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    四、getter|setter

    ● 属于属性描述符的一种

    1、默认的[[Get]]/[[Put]]操作

    let obj = {a: 1};
    
    obj.a; // [[Get]]
    
    obj.a = 3; // [[Put]]赋值操作;
    /**
    1. 先查找:getter、setter操作
    2. 查看属性描述符writable是否可写
    3. 赋值
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • [[Get]]: 查找当前属性,如果没有,查找原型
    • [[Put]]:
      a. getter|setter 本质上是改写获取属性的方式和赋值属性的方式
      b. 查找writable:false 是否让你修改
      c. 赋值

    2、getter

    • 伪属性 get
    var obj = {
      log: ['apple', 'orange'],
      get latest() { // 伪属性 get
        if(this.log.length === 0) {
          return undefined;
        }
        return this.log[this.log.length - 1];
      }
      
    }
    
    console.log(obj.latest); // orange
    console.log(obj.log.length); // 2
    var obj = {
      get a() {
        return 2;
      }  
    }
    
    Object.defineProperty(obj, 'b', {
      get: function() {
        return this.a * 3;
      },
    
    });
    
    console.log(obj.a); // 2
    console.log(obj.b); // 6
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 使用Object.defineProperty定义的属性值由get来设置的时候,不可以设置他的属性描述符:value、writable,其余两个是可以使用的
    Object.defineProperty(obj, 'b', {
      get: function() {
        return this.a * 3;
      },
        
      value: 3, // 报错
      writable: true, // 报错,false也一样
    });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、setter

    var language = {
      set current(name) {
        this.log.push(name);
      },
    
      log: []
    }
    
    language.current = 'en';
    language.current = 'ch';
    
    console.log(language.log); // [ 'en', 'ch' ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    4、综合使用getter|setter

    • 覆盖原本的[[Get]]/[[Put]]操作
    var obj = {
      get a() {
        return this._a;
      },
      
      set a(val) {
        this._a = val * 2;
      }
    }
    
    obj.a = 10;
    
    console.log(obj.a); // 20
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
  • 相关阅读:
    机器学习整理(神经网络)
    LeetCode题解-让所有学生保持开心的分组方法数
    mybatis的一级缓存和二级缓存
    STM8 调试总结
    零极点分析
    oracle 11g impdp命令导入dmp文件
    真题集P119---2013年真题
    谈谈数据决策平台搭建的必要性
    ChatGPT 与 Midjourney 强强联手,让先秦阿房宫重现辉煌!
    2023/09/12 qt&c++
  • 原文地址:https://blog.csdn.net/Lyb__/article/details/125490425