资讯专栏INFORMATION COLUMN

深入理解ES6笔记(四)扩展的对象功能

awkj / 2587人阅读

摘要:主要知识点有对象类别属性速记法方法简写需计算属性名方法方法可允许重复的属性自有属性的枚举顺序方法引用方法定义深入理解笔记目录对象类别普通对象拥有对象所有默认的内部行为。奇异对象其内部行为在某些方面有别于默认行为。所有的标准对象都是内置对象。

主要知识点有对象类别、属性速记法、方法简写、需计算属性名、Object.is()方法、Object.assign()方法、可允许重复的属性、自有属性的枚举顺序、Object.setPrototypeOf()方法、super引用、方法定义

《深入理解ES6》笔记 目录

对象类别

普通对象:拥有 JS 对象所有默认的内部行为。

奇异对象:其内部行为在某些方面有别于默认行为。

标准对象:在 ES6 中被定义的对象,例如 Array 、 Date ,等等。标准对象可以是普通的,也可以是奇异的。

内置对象:在脚本开始运行时由 JS 运行环境提供的对象。所有的标准对象都是内置对象。

对象字面量语法的扩展 属性初始化器的速记法

属性初始化器的速记法可以用来消除属性名和本地变量的重复情况,可以使用作用域内的变量值赋值给同名属性:

ES5 及更早版本中:

function createPerson(name, age) {
    return {
        name: name,
        age: age
    };
}

ES6简写:

function createPerson(name, age) {
    return {
        name,
        age
    };
}
方法简写

在对象字面量的写法中,为一个对象添加一个方法,需要指定对象的属性以及具体的函数声明。ES6提供了一种方法简写语法,通过省略function关键字,能够让为对象添加方法的语法更加简洁。
ES5中的写法:

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

ES6简写语法:

var person = {
    name: "Nicholas",
    sayName() {
        console.log(this.name);
    }
};
需计算属性名

需计算属性名规则允许对象字面量中属性名是变量、字符串字面量或者由变量计算而得的,具体写法是通过方括号[]包含属性名。

var lastName = "last name";
var person = {
    "first name": "Nicholas",
    [lastName]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person[lastName]); // "Zakas"

var suffix = " name";
var person = {
    ["first" + suffix]: "Nicholas",
    ["last" + suffix]: "Zakas"
};
console.log(person["first name"]); // "Nicholas"
console.log(person["last name"]); // "Zakas"

const id = 5
const obj = {
  [`my-${id}`]: id
}
console.log(obj["my-5"]) // 5
新的方法:Object.is()和Object.assign() Object.is() 方法

JS中比较两个值是否相同的时候会使用严格等于运算符===,但是,使用严格运算符式,+0和-0会认为这两者是相等的,而NaN===NaN是不相等的,使用Object.is()方法来判断这两者情况与使用严格相等符会有所不同,其他情况和使用严格相等运算符基本一致;

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

混入( Mixin )是在 JS 中组合对象时最流行的模式。在一次混入中,一个对象会从另一个对象中接收属性与方法。
下面是一个mixin方法的实现,这个方法实现的是浅拷贝。将b对象的属性拷贝到了a对象,合并成一个新的对象。

//mixin不只有这一种实现方法。
function mixin(receiver, supplier) {
  Object.keys(supplier).forEach((key) => {
    receiver[key] = supplier[key]
  })
  return receiver
}

let a = {name: "sb"};
let b = {
  c: {
    d: 5
    }
  }
console.log(mixin(a, b)) // {"name":"sb","c":{"d":5}}

写这样一个mixin方法是不是很烦,而且每个项目都得引入这个方法,现在,ES6给我们提供了一个现成的方法Object.assign()来做mixin的事情。

假设要实现上面的mixin方法,你只需要给Object.assign()传入参数即可。

console.log(Object.assign(a, b))// {"name":"sb","c":{"d":5}}
重复的对象字面量属性

ES5 严格模式为重复的对象字面量属性引入了一个检查,若找到重复的属性名,就会抛出错误。

"use strict";
var person = {
    name: "Nicholas",
    name: "Greg" // 在 ES5 严格模式中是语法错误
};

ES6 移除了重复属性的检查,严格模式与非严格模式都不再检查重复的属性。当存在重复属性时,排在后面的属性的值会成为该属性的实际值:

"use strict";
var person = {
    name: "Nicholas",
    name: "Greg" // 在 ES6 严格模式中不会出错
};
console.log(person.name); // "Greg"
自有属性的枚举顺序

ES5 并没有定义对象属性的枚举顺序,而是把该问题留给了 JS 引擎厂商。而 ES6 则严格定义了对象自有属性在被枚举时返回的顺序。这对 Object.getOwnPropertyNames() 与Reflect.ownKeys)如何返回属性造成了影响,还同样影响了Object.assign() 处理属性的顺序。
自有属性枚举时基本顺序如下:

所有的数字类型键,按升序排列。

所有的字符串类型键,按被添加到对象的顺序排列。

所有的符号类型(详见第六章)键,也按添加顺序排列。

const state = {
  id: 1,
  5: 5,
  name: "eryue",
  3: 3
}

Object.getOwnPropertyNames(state) 
//["3","5","id","name"] 枚举key

Object.assign(state, null)
//{"3":3,"5":5,"id":1,"name":"eryue"} 
for-in  循环的枚举顺序仍未被明确规定,因为并非所有的 JS 引擎都采用相同的方式。而  Object.keys()  和  JSON.stringify()  也使用了与  for-in  一样的枚举顺序。
更强大的原型

一般来说,对象的原型会在通过构造器或 Object.create() 方法创建该对象时被指定。
ES5 添加了 Object.getPrototypeOf() 方法来从任意指定对象中获取其原型;
缺少在初始化之后更改对象原型的标准方法。

修改对象的原型

ES6 通过添加 Object.setPrototypeOf() 方法而改变了这种假定,此方法允许你修改任意指定对象的原型。它接受两个参数:需要被修改原型的对象,以及将会成为前者原型的对象

let person = {
    getGreeting() {
        return "Hello";
    }
};
let dog = {
    getGreeting() {
        return "Woof";
    }
};
// 原型为 person
let friend = Object.create(person);
console.log(friend.getGreeting()); // "Hello"
console.log(Object.getPrototypeOf(friend) === person); // true
// 将原型设置为 dog
Object.setPrototypeOf(friend, dog);
console.log(friend.getGreeting()); // "Woof"
console.log(Object.getPrototypeOf(friend) === dog); // true
使用 super 引用的简单原型访问

能够使用super引用,来访问原型中的方法:

const proto = {
  foo: "hello"
};

const obj = {
  foo: "world",
  find() {
    return super.foo;
  }
};

Object.setPrototypeOf(obj, proto);
obj.find() // "hello"

注意,super关键字表示原型对象时,只能用在对象的简写方法之中,用在其他地方都会报错。

// 报错
const obj = {
  foo: super.foo
}

// 报错
const obj = {
  foo: () => super.foo
}

// 报错
const obj = {
  foo: function () {
    return super.foo
  }
}

javaScript 引擎内部,super.foo等同于Object.getPrototypeOf(this).foo(属性)或Object.getPrototypeOf(this).foo.call(this)(方法)。

const proto = {
  x: "hello",
  foo() {
    console.log(this.x);
  },
};

const obj = {
  x: "world",
  foo() {
    super.foo();
  }
}

Object.setPrototypeOf(obj, proto);

obj.foo() // "world"

上面代码中,super.foo指向原型对象proto的foo方法,但是绑定的this却还是当前对象obj,因此输出的就是world。

正式的“方法”定义

ES6 则正式做出了定义:方法是一个拥有 [[HomeObject]] 内部属性的函数,此内部属性指向该方法所属的对象。

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

大多数情况下,这种差异并不重要,然而使用 super 引用时就完全不同了。

let person = {
    getGreeting() {
        return "Hello";
    }
};
// 原型为 person
let friend = {
    getGreeting() {
        return super.getGreeting() + ", hi!";
    }
};
Object.setPrototypeOf(friend, person);
console.log(friend.getGreeting()); // "Hello, hi!"

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108409.html

相关文章

  • 深入理解ES6笔记——扩展对象功能性(4)

    摘要:将对象的属性拷贝到了对象,合并成一个新的对象。而这种行为也是新增的标准。总结本章讲解了对象字面量语法拓展,新增方法,允许重复的对象字面量属性,自有枚举属性排序,增强对象原型,明确了方法的定义。但是,就算把全部新增的功能记住也不是难事。 变量功能被加强了、函数功能被加强了,那么作为JavaScript中最普遍的对象,不加强对得起观众吗? 对象类别 在ES6中,对象分为下面几种叫法。(不需...

    baihe 评论0 收藏0
  • 深入理解ES6笔记——扩展对象功能性(4)

    摘要:将对象的属性拷贝到了对象,合并成一个新的对象。而这种行为也是新增的标准。总结本章讲解了对象字面量语法拓展,新增方法,允许重复的对象字面量属性,自有枚举属性排序,增强对象原型,明确了方法的定义。但是,就算把全部新增的功能记住也不是难事。 变量功能被加强了、函数功能被加强了,那么作为JavaScript中最普遍的对象,不加强对得起观众吗? 对象类别 在ES6中,对象分为下面几种叫法。(不需...

    Amos 评论0 收藏0
  • 深入理解ES6笔记——导读

    摘要:最近买了深入理解的书籍来看,为什么学习这么久还要买这本书呢主要是看到核心团队成员及的创造者为本书做了序,作为一个粉丝,还是挺看好这本书能给我带来一个新的升华,而且本书的作者也非常厉害。 使用ES6开发已经有1年多了,以前看的是阮一峰老师的ES6教程,也看过MDN文档的ES6语法介绍。 最近买了《深入理解ES6》的书籍来看,为什么学习ES6这么久还要买这本书呢?主要是看到Daniel A...

    Godtoy 评论0 收藏0
  • 深入理解ES6笔记——导读

    摘要:最近买了深入理解的书籍来看,为什么学习这么久还要买这本书呢主要是看到核心团队成员及的创造者为本书做了序,作为一个粉丝,还是挺看好这本书能给我带来一个新的升华,而且本书的作者也非常厉害。 使用ES6开发已经有1年多了,以前看的是阮一峰老师的ES6教程,也看过MDN文档的ES6语法介绍。 最近买了《深入理解ES6》的书籍来看,为什么学习ES6这么久还要买这本书呢?主要是看到Daniel A...

    wupengyu 评论0 收藏0
  • 深入理解ES6笔记(十一)代理(Proxy)和反射(Reflection)API(12)

    摘要:是陷阱函数对应的反射方法,同时也是操作的默认行为。对象外形指的是对象已有的属性与方法的集合,由于该属性验证只须在读取属性时被触发,因此只要使用陷阱函数。无论该属性是对象自身的属性还是其原型的属性。 主要知识点:代理和反射的定义、常用的陷阱函数、可被撤销的代理、将代理对象作为原型使用、将代理作为类的原型showImg(https://segmentfault.com/img/bVbfWr...

    explorer_ddf 评论0 收藏0

发表评论

0条评论

awkj

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<