zoukankan      html  css  js  c++  java
  • ES6 学习笔记之四 对象的扩展

    ES6 为对象字面量添加了几个实用的功能,虽然这几个新功能基本上都是语法糖,但确实方便。

    一、属性的简洁表示法

    当定义一个对象时,允许直接写入一个变量,作为对象的属性,变量名就是属性名。

    例1:

    var x = 2, y = 3,
    o = {
        x,
        y
    }

    与例2:

    var x = 2, y = 3,
    o = {
        x: x,
        y: y
    }

    是相同的。

    二、方法的简洁表示法

    下面的例子是方法的简洁表示法(例3)

    let o = {
        m (x) {
            console.log(x);
        }
    }
    o.m("Hello!");

    和下例是完全等同的(例4)

    let o = {
        m: function (x) {
            console.log(x);
        }
    }
    o.m("Hello!");

    由于例3和例4完全相同,也就是说例3中的函数也是匿名函数,不能在函数内部使用函数名调用自身,因此下例(例5)这种使用命名函数定义方法,并作自我调用的情况,是不能使用方法的简洁表示法的:

    let o = {
        factorial: function factorial (x) {
            if (x > 1) {
                return x * factorial(x - 1)
            } else {
                return 1;
            }
        }
    }
    console.log(o.factorial(5));

    三、 属性名表达式

    ES6 允许在字面量定义对象时,使用表达式做属性名和方法名,示例如下(例6):

     1 let firstName = 'first';
     2 let secondFrontName = 'se';
     3 let secondBehandName = 'cond';
     4 let funcName = function () {
     5     return 'func';
     6 }
     7 let methodName1 = 'sayHello';
     8 let methodName2 = 'sayBye';
     9 let obj = {
    10     [firstName]: 'hello',
    11     [secondFrontName + secondBehandName]: 'world',
    12     [funcName()]: 'bye',
    13     [methodName1]() {
    14     console.log('Hello, world!');
    15     },
    16     [methodName2]: function () {
    17     console.log('Goodbye!');
    18   }
    19 }
    20 console.log(obj[firstName]);
    21 console.log(obj[secondFrontName + secondBehandName]);
    22 console.log(obj[funcName()]);
    23 obj.sayHello();
    24 obj.sayBye();

    注意,在第13行时,同时使用了属性名表达式和方法的简洁表示法,这是没问题的。

    但是不能同时使用属性名表达式和属性的简洁表示法,会报错(例7):

    let foo = 'bar';
    let bar = 'abc';
    let baz = { [foo] };

    四、操作[Prototype]

    作为原型继承语言,在JavaScript中,prototype属性是非常重要的。在前ES6中,浏览器提供了扩展的属性__proto__,来获取和设置它。

    ES6 将这个属性放在了标准的附录部分,并且说明仅要求浏览器实现这个属性,也就是说只有在浏览器中的脚本使用这个属性才是安全可信赖的。

    为保持对特定环境的非依赖,不应该在代码中使用这个属性。而应该使用 Object.setPrototypeOf(...) 和 Object.getPrototypeOf(...) 方法设置和获取,这两个方法是全环境安全的。

    例8:

    1 let proto = {};
    2 proto.y = 20;
    3 let obj = {x : 10};
    4 console.log(Object.getPrototypeOf(obj));
    5 console.log(obj.y);
    6 Object.setPrototypeOf(obj, proto);
    7 console.log(Object.getPrototypeOf(obj));
    8 console.log(obj.y);

    第四行的结果显示,obj 的 [prototype] 是 Object,并且第五行获得的 y 属性为 undefined。

    经过第6行的设置,obj 的 [prototype] 就是proto对象了,并且第8行 obj 的 y 属性是循着原型链获取到的 proto 对象的 y 属性的值。

    五、super

    super 可以用来调用原型链上的方法,如下例(例9):

    let proto = {
        foo () {
            console.log("I'm proto foo.");
        }
    }
    let parent = {
    
    }
    let obj = {
        foo () {
            super.foo();
            console.log("I'm obj foo.");
        }
    }
    Object.setPrototypeOf(parent, proto)
    Object.setPrototypeOf(obj, parent);
    obj.foo(); // I'm proto foo.
    // I'm obj foo.

    super 只能出现在方法的简洁表示法定义中,如下例(例10)这样是会报错的:

    let proto = {
        foo () {
            console.log("I'm proto foo.");
        }
    }
    let parent = {
    
    }
    let obj = {
        foo: function () {
            super.foo();
            console.log("I'm obj foo.");
        }
    }
    Object.setPrototypeOf(parent, proto)
    Object.setPrototypeOf(obj, parent);
    obj.foo();

    对于要调用的方法是不是用简洁表示法定义的,则没有限制,如下例(例11):

    let proto = {
        foo: function () {
            console.log("I'm proto foo.");
        }
    }
    let parent = {
    
    }
    let obj = {
        foo () {
            super.foo();
            console.log("I'm obj foo.");
        }
    }
    Object.setPrototypeOf(parent, proto)
    Object.setPrototypeOf(obj, parent);
    obj.foo();

    六、 Object.is()方法和Object.assign()方法

    Object.is() 方法用来比较两个对象是否严格相等,它的行为与 === 极为相似,不同点有二:

    1. +0 和 -0

    对于 === 运算符,+0 和 -0 是相等的,而 Object.is()则认为这两个值不同。

    +0 === -0; // true
    Object.is(+0, -0); // false

    2. NaN 和 NaN

    对于 === 运算符,NaN 和 NaN 是不等的,Object.is() 则认为这是相同的。

    NaN == NaN; // false
    Object.is(NaN, NaN); // true

    Object.assign() 方法用来将一个至多个对象的可枚举属性拷贝到目标对象中。

    Object.assign()方法的第一个参数是目标对象,后续的参数为源对象(参数必须是对象)。如果对象中有相同名称的属性,则排列在后的对象的属性会覆盖排在前面的对象的同名属性。(这个方法,有点像 JQuery 中的 extend 方法)

    例12:

    let obj1 = {};
    let obj2 = {
        prop: "I'm property",
        func () {
            return "I'm function.";
        }
    }
    Object.assign(obj1, obj2);
    console.log(obj1);
    console.log(obj1.func());

    这一方法的限制是:它只复制自身的可枚举属性,继承来的属性不复制,不可枚举属性也不复制;另外它的复制是浅拷贝,即只处理一级属性的添加和替换,嵌套属性不处理。

    如下例(例13)

    let target = { a: { b: 'c', d: 'e' } };
    let source = { a: { b: 'hello' } };
    Object.assign(target, source); // { a: { b: 'hello' } }

    注意此例的结果,target 的 a 属性被 source 的 a 属性完全替换,而不是 source 中 a 属性的 b 嵌套属性替换了 target 中 a 属性的 b 嵌套属性。如果你期望的结果是  { a: { b: 'hello', d: 'e' } } ,你可要失望了。

  • 相关阅读:
    20200414:mysql原子性和持久性怎么保证
    20200417:说说redis的rdb原理。假设服务器的内存8g,redis父进程占用了6g,子进程fork父进程后,子父进程总共占用内存12g,如何解决内存不足的问题?(挖)
    [九省联考2018]秘密袭击coat
    CF1158F Density of subarrays
    忘情
    [IOI2018] meetings 会议
    [AGC013E] Placing Squares
    [八省联考2018]林克卡特树
    [NOI2016] 国王饮水记
    [十二省联考 2019]皮配
  • 原文地址:https://www.cnblogs.com/matchless/p/9355943.html
Copyright © 2011-2022 走看看