• ES6拓展的对象功能


    前言:因为之前看过很多的博客啊,书籍啊但是最后都雁过无痕,再问我基本没什么印象,所以就迫使自己看书的时候记点笔记,因为懒得写字[捂脸],现在是打字比写字要快好多,所以就写博客吧!

    ES6规范明确定义了对象的每种类别:1,普通对象 ;2:奇异对象;3 标准对象;4内置对象。

    对象字面量语法的拓展:

    ES5中对象字面量是简单的“键/值对”集合,这意味着初始化属性值的代码可能会有些重复:

    function createPeople(name,age){
        return {
            name:name,
            age:age
        }
    }
      function createPeople(name,age){
         return {
             name,
             age
         }
      }

    这个函数创建了一个对象,其属性名和函数的参数名相同,看起来是重复了name和age。键值是重复的。ES6中可以简单书写名称省略冒号和值。当对象字面量中的属性只有名称时,JS引擎会在周边作用域查找同名变量。若找到就赋值给同名属性。

    方法简写:

    var person = {
        name:'Miya',
        sayName:function(){
            console.log(this.name);
        }
    }
    
    var person = {
        name:"Miya",
        sayName(){
            console.log(this.name);
        }
    }
    person.sayName(); //Miya

    方法简写能使用super,非简写方法则不能。

    可计算属性名:

     方括号允许指定变量或者字符串字面量为属性名。

    var person = {},lastName = "last name";
    person["age"] = "26";
    person[lastName] = "Miya";
    console.log(person) //{age: "26", last name: "Miya"}

    lastName变量的值为"last name",属性名中包含空格,这种情况无法用小数点表示法进行属性的访问,而方括号表示法允许将任意字符串用作属性名。

    如果属性名事先已知,可以使用字符串字面量表示,但是,如果属性名被包含在变量中,或则和必须通过计算获得,那么ES5中就无法对对象字面量定义这种属性。

    ES6中,可计算属性名是对象字面量语法的一部分,用方括号表示。

    var lastName = "last name";
    var person = {
        "first name":"Miya",
        [lastName]:"Tang"
    }
    console.log(person[lastName])   //Tang
      var suff = " name";
      var person = {
       [`first ${suff}`]:"Miya",
       [`last ${suff}`]:"Tang"
      }
      console.log(person); //{first name: "Miya", last name: "Tang"}

    对象字面量中的方括号表明该属性名需要计算,其结果是一个字符串,那么其中就可以包含表达式了。类似上面的形式。使用方括号表示法,任何能放在对象实例方括号内的东西,都可以作为可计算属性名用在对象字面量中。

     新的方法:

    从ES5开始就有一个设计意图:避免创建新的全局变量,避免在Object原型上添加新的方法,尽量尝试将新方法添加到合适的对象上。ES6在Object对象上引入了两个新方法:

    Object.is()和Object.assin()

     JS中进行比较两个值时,会使用(==)和(===),为了避免强制类型转换,开发者更倾向于使用严格相等运算符。但是严格相等也不是完全准确,例如:+0和-0相等,NaN ===NaN,会返回false,因此只有isNaN函数才能正确金策NaN。

    ES6的Object.is()方法来弥补严格相等运算符残留的怪异缺陷。方法中接受两个参数,看下面的栗子:

    console.log(+0 === -0)  //true
    console.log(Object.is(+0,-0)) //false
    
    console.log(NaN === NaN)    //false
    console.log(Object.is(NaN,NaN))  //true
    
    console.log(5 == '5')  //true
    console.log(Object.is(5,"5"));    //false

    Object.assign()方法:

    混入(Mixin)是JS中组合对象时最流行的模式。

    function mixin(receiver,supplier){
        Object.keys(supplier).forEach(function(key){
            receiver[key] = supplier[key];
        })
        return receiver;
    }

    minxin()函数在supplier对象的自我属性上进行迭代。将这些属性赋值到receiver对象上(浅复制,当属性值为对象时,仅复制其引用),receiver对象就能获得新的属性而无须使用继承。

    各式各样的库中都有相似但是名称不同的方法,流行的有:extend()或者minx(),基本功能都相同。还有一个Object.mixin()方法,但是Object.mixin()也会赋值访问器属性,考虑到super的使用,此方法最终被移除了。 

    var receiver = {};
    var obj1 = {type:'js',name:"file.js"};
    var obj2 = {type:'css'}
    Object.assign(receiver,obj1,obj2)
    {type: "css", name: "file.js"}

    在接收对象中,后面的源对象属性会覆盖前面的。注意点:Object.assing()不能将源对象的访问器属性复制到接收对象中,由于源对象的访问器属性会转变成接收对象的数据属性。

    var receiver = {};
    var supplier = {
        get name(){
            return "file.js"
        }
    };
    Object.assign(receiver,supplier);
    console.log(receiver);
    //{name: "file.js"}

    重复的对象字面量属性:

    ES5中严格模式下重复对象字面量属性会报错。ES6移除了重复属性的检查,无论是否是严格模式,当存在重复属性时,排在后面的属性的值会成为该属性的实际值。

    "use strict";
    var person = {
        name:"miya",
        name:'tang'
    }
    console.log(person)
    //{{name: "tang"}}

    自有属性的枚举顺序:

     ES5没有定义对象属性的枚举顺序,ES6则严格定义了对象自有属性在被枚举时候的返回顺序。

    var person = {
        name:"miya",
        age:'26',
        sex:'female'
    }
    Object.getOwnPropertyNames(person)
    (3) ["name", "age", "sex"]
    Reflect.ownKeys(person)
    (3) ["name", "age", "sex"]
    var obj = {
    a:1,
    0:1,
    c:1,
    2:1,
    b:1,
    1:1
    }
    obj.d = 1;
    console.log(Object.getOwnPropertyNames(obj).join("")) //'012acbd'

    基本顺序:1,所有的数字类型,按照升序排列。2,字符串类型按被添加到对象的顺序排列。3,符号类型键按添加顺序来。

    更强大的原型:

    一般情况,对象的原型会通过构造器或者Object.create()方法创建对象时指定。ES6通过添加Object.setPrototypeOf()方法允许你修改任意指定对象的原型。接受两个参数,需要被修改原型对象,将会成为前者原型的对象。栗子如下:

    let person = {
        getGreeting(){
            return "hello"
        }
    }
    let dog = {
        getGreeting(){
            return "Woof"
        }
    }
    
    let friend = Object.create(person);
    console.log(friend.getGreeting())  //hello
    console.log(Object.getPrototypeOf(frined) === person) //true
    
    Object.setPrototypeOf(friend,dog);
    console.log(friend.getGreeting())   //Woof
    console.log(Object.getPrototypeOf(friend) === dog)  //true

    可以看出:Object.setPrototypeOf()方法能够修改对象的原型。

    使用super引用的简单原型访问:

    super引用能够更轻易地在对象原型上进行功能调用。 

    let person = {
        getGreeting(){
            return "hello"
        }
    }
    let dog = {
        getGreeting(){
            return "Woof"
        }
    }
    let friend = {
        getGreeting(){
            //原型上的getGreeting方法调用本身this对象
            return Object.getPrototypeOf(this).getGreeting.call(this)+',hi!';
        }
    }

    //使用super进行简化
    let friend = {

         getGreeting(){
            //原型上的getGreeting方法调用本身this对象
            return super.getGreeting()+',hi!';
         }
      }

      Object.setPrototypeOf(friend,person);

      console.log(friend.getGreeting()) //hello,hi!

    
    Object.setPrototypeOf(friend,dog);
    console.log(friend.getGreeting()) //Woof,hi!

    friend上的getGreeting()调用了对象上的同名方法。调用原型上的方法用:Object.getPrototypeOf()和call(this),有点复杂,所以ES6引入了super,用来指向当前对象的原型的一个指针,相当于Object.getPrototypeOf(this)的值。可以使用super引用来调用对象原型上的任何方法。

    需要注意点:super引用只能是位于简写方法,如果方法简写之外情况用super就会报错!!!

    let friend = {
        getGreeting(){
            return super.getGreeting()+',hi!';
        }
    }
    //'Uncaught SyntaxError: 'super' keyword unexpected here

    这里举个由于this指向变化导致递归调用的栗子,而用super的话可以很好的解决this指向动态的问题,看下面的栗子:

    let person = {
        getGreeting(){
            return "hello"
        }
    }
    let friend = {
        getGreeting(){
            //原型上的getGreeting方法调用本身this对象,如果是relative,此时this就是relative,Object.getPrototypeOf(this)就是friend,然后call(this)...
            return Object.getPrototypeOf(this).getGreeting.call(this)+',hi!';
        }
    }
    
    Object.setPrototypeOf(friend,person);
    let relative = Object.create(friend);
    relative.getGreeting()
    //VM91:7 Uncaught RangeError: Maximum call stack size exceeded

    可以看出发出堆栈错误,因为此时的this指向relative,而relative的原型是friend对象,friend.getGreeting().call()调用会导致进程开始反复进行递归调用,发生堆栈错误。

    而如果用super引用的话:

    let person = {
        getGreeting(){
            return "hello"
        }
    }
    let friend = {
        getGreeting(){
            //super引用会一直指向person
            return super.getGreeting()+',hi!';
        }
    }
    
    Object.setPrototypeOf(friend,person);
    let relative = Object.create(friend);
    relative.getGreeting()
    //"hello,hi!"

    因为super总是能指向正确的对象,本栗子中super.getGreeting()总是指向person.getGreeting(),不管有多少对象继承了此方法。

    正式的“方法”定义:

    let person = {
        //方法
        getGreeting(){
            return "hello!"
        }
    }
    //并非方法
    function shareGreeting(){
        return 'Hi!'
    }

    getGreeting()直接赋值给了一个对象,它的HomeObject属性值就是person,shareGreeting()函数被创建时候没有赋给一个对象,没有HomeObject属相。差异在于使用super引用时。

    任何对super的引用第一步:在HomeObject上调用Object.getPrototypeOf()来获取原型的引用,第二部:在该原型上查找同名函数,第三部:创建this绑定并调用该方法。

     关键字:【对象】【同名属性】【可计算属性名】【方法简写】【Object.is()】【Object.assign()】【枚举顺序】【Object.setPrototypeOf()】【super】

    世界上只有一种真正的英雄主义,那就是认清生活的真相后还依然热爱生活。 ——《米开朗基罗》罗曼罗兰

  • 相关阅读:
    W3C help
    css值解析
    css中的格式上下文Formatting Context
    css中绝对定位中的left和top属性
    事件模型
    程序员应该如何更有效率
    css的边偏移距离
    css插入框
    css中的whitespace属性
    源码安装nginx 方法二
  • 原文地址:https://www.cnblogs.com/tangjiao/p/9259057.html
Copyright © 2020-2023  润新知