对象

继承

原型链:

  1. 实例对象通过 __proto__ 属性或 Object.getPrototypeOf() 访问原型对象;
  2. null 没有原型对象,并且是原型链的最后一个环节;
  3. 访问对象的属性时会从自身开始沿原型链查找,直到找到或到尾。

一个字面量的原型链如下:

字面量 ---> 内置对象.prototype ---> Object.prototype ---> null

当继承的函数被调用时,this 指向的是当前继承的实例对象而非继承的函数所在的原型对象。

可以通过以下几种方式来创建对象和生成原型链:

  1. 语法结构(字面量);
  2. 构造函数;
  3. Object.create() 方法;
  4. class 关键字。

复制

对象的复制分为浅复制和深复制两种。

浅复制的特点:

  1. 只复制一层对象属性;
  2. 单纯地复制源对象的属性,如果值是对象就复制该对象的引用地址;
  3. 目标对象不会开辟新的栈,与源对象共享。

深复制的特点:

  1. 将源对象的属性递归复制到目标对象上;
  2. 开辟新的栈存储目标对象的属性。

最简单省力的深复制可以通过调用 JSON.parse()JSON.stringify() 来实现。但这种方式有个缺陷,就是源对象必须符合 JSON 规范。完全的深复制只能通过手写递归来实现。

属性

获取属性

通过 Object.keys()for...in 可以获取到指定对象的可枚举属性,但 for...in 获取到的值中包含了通过 prototype 继承而来的。如果想同时获取到不可枚举的属性的话,可以使用 Object.getOwnPropertyNames()

// 定义一个构造函数
function Demo() {}

// 给构造函数的原型添加可枚举属性
['set', 'get', 'has'].forEach(function( m ) {
  Demo.prototype[m] = function() {};
});

// 给构造函数的原型添加不可枚举属性
Object.defineProperty(Demo.prototype, 'see', {
  value: function() {},
  enumerable: false
});

// 创建实例
const inst = new Demo();

// 给实例添加可枚举属性
Object.assign(inst, {a: 1, b: '2'});

// 给实例添加不可枚举属性
Object.defineProperty(inst, 'c', {
  value: function() {},
  enumerable: false
});

// 输出的是实例本身的可枚举属性
console.log('Object.keys(): ', Object.keys(inst));

const result = [];

for ( let p in inst ) {
  result.push(p);
}

// 输出的是实例本身及从原型继承的可枚举属性
console.log('for...in: ', result);

// 输出的是实例本身的可枚举和不可枚举的属性
console.log('Object.getOwnProperyNames() for inst: ', Object.getOwnPropertyNames(inst));

// 输出的是原型本身的可枚举和不可枚举的属性
console.log('Object.getOwnProperyNames() for Demo.prototype: ', Object.getOwnPropertyNames(Demo.prototype));

资料

results matching ""

    No results matching ""