Object 对象的相关方法
- Object.getPrototypeOf()
- 返回参数对象的原型。
- 这是获取某对象的原型对象的标准方法。
-
var F = function () {}; var f = new F(); Object.getPrototypeOf(f) === F.prototype // true
-
- 几种特殊对象的原型
-
// 空对象的原型是 Object.prototype Object.getPrototypeOf({}) === Object.prototype // true // Object.prototype 的原型是 null Object.getPrototypeOf(Object.prototype) === null // true // 函数的原型是 Function.prototype function f() {} Object.getPrototypeOf(f) === Function.prototype // true
-
- Object.setPrototypeOf()
- 重新指定 某对象 的原型对象,返回 某对象。
- 第一参数是 某对象
- 第二参数是 新的原型对象
-
var a = {}; var b = {x: 1}; Object.setPrototypeOf(a, b); Object.getPrototypeOf(a) === b // true a.x // 1
将对象 a 的原型,设置为对象 b,因此 a 可以共享 b 的属性
-
- 模拟 new 创建实例
-
var F = function () { this.foo = 'bar'; }; var f = new F(); // 等同于 var f = Object.setPrototypeOf({}, F.prototype); // 将一个空对象的原型设为构造函数的prototype属性 F.call(f); // 将构造函数内部的this绑定这个空对象,然后执行构造函数,使得定义在this上面的方法和属性(上例是this.foo),都转移到这个空对象上
-
- Object.create()
- 很多时候,只能拿到一个实例对象,它可能根本不是由构建函数生成的
- Object.create() 接收一个实例对象,以它为原型,再创建并返回一个实例对象。
-
// 原型对象 var A = { print: function () { console.log('hello'); } }; // 实例对象 var B = Object.create(A); Object.getPrototypeOf(B) === A // true B.print() // hello B.print === A.print // true
以 A 对象为原型,生成了 B 对象。B 继承了 A 的所有属性和方法
-
- 如果想要生成一个不继承任何属性(比如没有 toString() 和 valueOf() 方法)的对象,可以将Object.create() 的参数设为null
- 注意: 参数不能为空,或者不是对象,否则会报错。可以是 null
- 生成的新对象,动态继承了原型
- 意味着在原型上添加或修改任何方法,会立刻反映在新对象之上
- 还可以接受第二个参数。该参数是一个属性描述对象,它所描述的对象属性,会添加到实例对象,作为该对象自身的属性
-
var obj = Object.create({}, { p1: { value: 123, enumerable: true, configurable: true, writable: true, }, p2: { value: 'abc', enumerable: true, configurable: true, writable: true, } }); // 等同于 var obj = Object.create({}); obj.p1 = 123; obj.p2 = 'abc';
-
- Object.create() 方法生成的对象,继承了它的原型对象的构造函数
-
function A() {} var a = new A(); var b = Object.create(a); b.constructor === A // true b instanceof A // true
上面代码中,b 对象的原型是 a 对象,因此继承了 a 对象的构造函数
-
- Object.prototype.isPrototypeOf()
- 用来判断该对象是否为某对象的原型
-
var o1 = {}; var o2 = Object.create(o1); var o3 = Object.create(o2); o2.isPrototypeOf(o3); // true o1.isPrototypeOf(o3); // true
-
- 只要实例对象处在参数对象的原型链上,isPrototypeOf() 方法都返回 true
- 由于Object.prototype处于原型链的最顶端,所以对各种实例都返回true,只有直接继承自 null 的对象除外
- 用来判断该对象是否为某对象的原型
- Object.prototype.__proto__ Object对象的 实例对象的 隐式原型对象
- 根据语言标准,__proto__属性只有浏览器才需要部署,其他环境可以没有这个属性
- 它前后的两根下划线,表明它本质是一个内部属性,不应该对使用者暴露
- 应该尽量少用这个属性,而是用 Object.getPrototypeof() 和 Object.setPrototypeOf(),进行原型对象的读写操作
- __proto__ 属性指向当前对象的原型对象,即构造函数的 prototype 属性
- 获取原型对象的方法的比较
- 获取实例对象 obj 的原型对象,有三种方法
- obj.__proto__ 只有浏览器才需要部署,其他环境可以不部署
- obj.constructor.prototype 在手动改变原型对象时,可能会失效
- 在改变原型对象时,一般要同时设置constructor属性
-
var P = function () {}; var p = new P(); var C = function () {}; C.prototype = p; C.prototype.constructor = C; var c = new C(); c.constructor.prototype === p // true
- Object.getPrototypeOf(obj) 最好的方法
- 获取实例对象 obj 的原型对象,有三种方法
- Object.getOwnPropertyNames()
- 返回一个数组,成员是参数对象本身的所有属性的键名(不管是否可以遍历enumerable),但是不包含继承的属性键名
- 只获取那些可以遍历的属性,使用 Object.keys(某对象) 方法
- Object.prototype.hasOwnProperty()
- 用于判断某个属性是否是自身的属性,是返回 true,否则返回 false
- 是 JavaScript 之中唯一一个处理对象属性时,不会遍历原型链的方法
- in 运算符
- 表示一个对象是否具有某个属性。
- 用于检查一个属性是否存在
- 它不区分该属性是对象自身的属性,还是继承的属性
'length' in Date // true 'toString' in Date // true
- for(...in...) 循环
- 获得对象的所有可遍历属性(不管是自身的还是继承的)
-
var o1 = { p1: 123 }; var o2 = Object.create(o1, { p2: { value: "abc", enumerable: true } }); for (p in o2) { console.info(p); } // p2 自身的属性 // p1 继承的属性
为了获得对象自身的属性,可以采用hasOwnProperty方法判断一下
-
for ( var name in object ) { if ( object.hasOwnProperty(name) ) { console.log(name); } }
-
-
- 获得对象的所有属性(不管是自身的还是继承的,也不管可否遍历),可以使用下面的函数
-
function inheritedPropertyNames(obj) { var props = {}; while(obj) { Object.getOwnPropertyNames(obj).forEach(function(p) { props[p] = true; }); obj = Object.getPrototypeOf(obj); // 原型对象的原型对象 } return Object.getOwnPropertyNames(props); }
inheritedPropertyNames(Date);
// [
// "caller",
// "constructor",
// "toString",
// "UTC",
// ...
// ]
-
- 获得对象的所有可遍历属性(不管是自身的还是继承的)
- 对象的拷贝
- 如果要拷贝一个对象,需要做到下面两件事情
- 确保拷贝后的对象,与原对象具有 同样的原型
- 确保拷贝后的对象,与原对象具有 同样的实例属性
- 确保拷贝后的对象,与原对象具有 同样的原型
- 第一种方法
-
function copyOwnPropertiesFrom(new, old) { Object.getOwnPropertyNames(old).forEach(function (propKey) { var desc = Object.getOwnPropertyDescriptor(old, propKey); Object.defineProperty(new, propKey, desc); }); return new; } function copyObject(old) { var new = Object.create(Object.getPrototypeOf(old)); copyOwnPropertiesFrom(new, old); return new; }
-
- 第二种更简单的写法,是利用 ES2017 才引入标准的Object.getOwnPropertyDescriptors方法
-
function copyObject(orig) { return Object.create( Object.getPrototypeOf(orig), Object.getOwnPropertyDescriptors(orig) ); }
-
- 如果要拷贝一个对象,需要做到下面两件事情