ES6新技术之 对象技术

1,393 阅读7分钟

========================

Summary

Objects are the center of JavaScript programming, and ECMAScript 6 makes some helpful changes to objects that make them easier to work with and more flexible.

「对象」/Object技术是JS开发中使用最多的技术之一。 ECMAScript 6 focuses heavily on making objects more useful, which makes sense because nearly every value in JavaScript is some type of object. The number of objects developers use in an average JavaScript program continues to increase as the complexity of JavaScript applications increases. With more objects in a pro­gram, it has become necessary to use them more effectively. 因为JS应用规模越来越大,对象越来越多(多应用角色,多结构层次的对象),对象的创建和使用应该尽可能的简洁。 ES6对对象这个工具作了多个优化改进,让它使用更加方便,和灵活。

所谓对象技术,是指Object对象作为一种计算容器的功能,它可装多个不同数据成员(键值对),以及与数据相关的函数方法成员。另外,两个对象之间的「原型关系」可以实现面向对象的程序构造任务;故对象技术既可用来处理单一的专用计算(包括无状态通用代码,少量状态的闭包,和无代码的键值对数据结构),也是实现层次化的程序工程复用的基础。

对象的形式

对象技术针对的编程任务包括对象的创建(字面量创建)、派生(对象继承)、使用(制作功能方法),而这些任务前提是我们对对象形式的理论有一定的基础。

对象的属性

对象形式实质就是计算任务,形式由本质属性组成。在制作和使用对象的活动中,对象存有两个不同角度:形式属性和结构成员。

形式属性与结构成员

对象,从一开始设计初衷,是有结构的,结构成份叫成员;成员是从质料的角度,一个对象的构造者(生产者)的角度。而相对的,对象属性,是呈现给使用者的功能,是从形式的角度,一个对象的使用者(消费者)的角度。对象的制作不但满足自己的计算需要,通用对象也是给项目内其它他计算任务(对象)使用,使用的就是对象的形式属性,包括数据属性和方法属性。

对象属性定义

从编程的角度,对象属性 笼统包括了属性名、值和一些元属性( attributes ):

an object property is a name, a value, and a set of attributes. 为了提供计算功能,对象每一个属性必须有一个标识,和标识所指示的计算资源。而所谓对象属性的attributes,是从制作「对象属性」的内部角度,生产者的需要的属性。例如所有的对象属性的都有[[value]] 成员属性。对象制作者利用对象属性的attributes制作对象属性,而对象使用者使用对象属性,制作更复杂计算任务。对象属性理解的困难在于,对象制作者常常也是对象的使用者。

属性种类

从形式的角度,对象属性只有数据属性和方法属性,从质料角度,数据属性由数据字段,和字段访问器两类组成。在对象使用者的角度,数据字段成员和访问器成员,都是提供计算数据资源。

Object Categories JavaScript uses different terminology to describe objects in the standard as opposed to those added by execution environments, such as the browser. The ECMAScript 6 specification has clear definitions for each object cate­ gory. It’s essential to understand this terminology to grasp the language as a whole. The object categories are: Ordinary objects Have all the default internal behaviors for objects in JavaScript. Exotic objects Have internal behavior that differs from the default in some way. Standard objects Defined by ECMAScript 6, such as Array , Date , and so on. Standard objects can be ordinary or exotic. Built-in objects Present in a JavaScript execution environment when a script begins to execute. All standard objects are built-in objects.

ES6

使用字面量创建 对象实例

ES6在对象字面量(object literals)上作多处改进:

第一,属性名简写

对象数据属性赋初始值的变量名可以直接用作对象对象属性名,简化代码;

const x = 4; const y = 1; const obj = { x, y }; // 相当于ES5: const obj = { x: x, y: y };

属性名简写很好配合新的对象解构赋值语法:

const obj = { x: 4, y: 1 }; const {x,y} = obj; console.log(x); // 4 console.log(y); // 1

对象访问器属性保持原样:

const obj = {
    get foo() {
        console.log('GET foo');
        return 123;
    },
    set bar(value) {
        console.log('SET bar to '+value);
        // return value is ignored
    }
};

第二,方法名简写

直接写「方法」名,无需再使用函数表达式,省去function和分号等字; Shorthand methods let you type far fewer characters to define methods on object literals by completely omitting the colon and function keyword.

const obj = {
    myMethod(x, y) {
        ···
    }
};

generator函数方法:

const obj = {
    * myGeneratorMethod() {
        ···
    }
};

第三,动态属性名

属性名可使用表达式,表达式可让属性使用非字面值,就是带变量,这个功能早在其它语言中可用;

在设置一个对象属性时,是一直可以用表达式的:

Via an expression: obj['b'+'ar'] = 123;

但是字面量创建,ES5不行,ES6增加了一这个语法:

1` 数据属性动态:

const obj = {
    foo: true,
    ['b'+'ar']: 123
};

2`方法名动态:

const obj = {
    ['h'+'ello']() {
        return 'hi';
    }
};
console.log(obj.hello()); // hi

The main use case for computed property keys is to make it easy to use symbols as property keys.

The main use case for computed property keys are symbols: you can define a public symbol and use it as a special property key that is always unique. One prominent example is the symbol stored in Symbol.iterator. If an object has a method with that key, it becomes iterable: The method must return an iterator, which is used by constructs such as the for-of loop to iterate over the object. The following code demonstrates how that works.

动态计算的属性名最典的用例,就是方便使用 symbols 作为属性名。最著名的就是Symbol.iterator 符号用作iterator的属性名。某个对象具有这个符号的属性的表明它是可迭代的(iterable)——给for-of等循环消费:

const obj = {
    * [Symbol.iterator]() { // (A)
        yield 'hello';
        yield 'world';
    }
};
for (const x of obj) {
    console.log(x);
}
// Output:
// hello
// world

第四,允许属性重名

ES6 放松在严格模式下对属性重名的检查;就是放宽了对重复对象字面量属性名称的严格模式检查,这意味着具有相同名称的两个属性可以在单个对象字面量定义中,而不会引发错误。

对象属性

复制或扩展对象实例的功能

The Object.assign() method makes it easier to change multiple properties on a single object at once and is very useful when you use the mixin pattern. Mixins are among the most popular patterns for object composition in JavaScript. 对象混入(Mixins)是JS中非流行的对象派生技术——合并两对象产生新对象的编程模式,因为它比原型继承实现对象复用更加的灵活(EM:有点像函数对象比较一般类对象更轻便一样)。例如,很多通用代码库都有类似如下的mixin函数:

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

通过 mixin 函数,接受都对象(receiver)无需通过原型继承机制,从提供者对象(supplier)上获得新的对象属性,例如如下的一个空对象,mixin了EventTarget.prototype的所有对象属性:


function EventTarget() { /*...*/ }
EventTarget.prototype = {
constructor: EventTarget,
emit: function() { /*...*/ },
on: function() { /*...*/ }
};
var myObject = {};
mixin(myObject, EventTarget.prototype);
myObject.emit("somethingChanged");

对象混入技术的需求如此之大,故ES6 提供了Object.assign() 。Object.assign() 较mixin函数更通用和灵活,它可mixin 任意个 supplier 合并给receiver。 This mixin pattern became popular enough that ECMAScript 6 added the Object.assign() method, which behaves the same way, accepting a receiver and any number of suppliers and then returning the receiver.

The most important new method of Object is assign(). Traditionally, this functionality was called extend() in the JavaScript world. In contrast to how this classic operation works, Object.assign() only considers own (non-inherited) properties.

!对象复制是意义、实现原理,和使用注意

Object.is()

The Object.is() method performs strict equality on any value, effectively becoming a safer version of === when you’re working with spe­ cial JavaScript values.

规定了对象自有属性的枚举顺序

ES5没有规定对象自有属性的枚举顺序,这是浏览器自己决定,这样影响了以下等API的一致使用:

  • Object.getOwnPropertyNames()
  • Reflect.ownKeys
  • Object.assign()

ECMAScript 6 清楚地定义了自有属性的枚举顺序。先是数字(以升序排列),接着是字符串(按插入顺序排列),最后符号键(按插入顺序排列):

var obj = {
a: 1,
0: 1,
c: 1,
2: 1,
b: 1,
1: 1
};
obj.d = 1;
console.log(Object.getOwnPropertyNames(obj).join(""));  // "012acbd"

原型继承

动态更改父原型

当我们用字面量创建一个动态对象,它的父原型对象是object,功能很简单的;我们可能需替换父原型来增加功能。ES6提供了新的标准API(以前是通用访问内部属性__proto__) Object.setPrototypeOf()

super访问父原型

此外,你可以使用 super 关键字调用父原型上的方法。使用 了 super 的方法内的 this,自动设置为 this 的当前值。

let friend = { getGreeting() { // in the previous example, this is the same as: // Object.getPrototypeOf(this).getGreeting.call(this) return super.getGreeting() + ", hi!"; } };

参考

exploringjs.com/es6/ch_oop-…

Using JavaScript Mixins alligator.io/js/using-js…