JS与原型有关的几个方法介绍

一、Object.create()方法

Object.cerate()方法用于从原型对象生成新的实例对象,可以替代new命令。它接受一个对象作为参数,返回一个新对象,返回对象完全继承参数对象的属性,即作为参数的对象成为返回的新对象的原型。

var A = {
    print: function () {console.log('hello');}
};
var B = Object.create(A);

B.print() // hello
B.print === A.print // true

//等同于以下代码
var A = function () {};
A.prototype = {
    print: function () {console.log('hello');}
};

var B = new A();
B.print === A.prototype.print // true

上面的代码中,Object.create方法在A的基础上生成了B。此时,A就成了B的原型,B就继承了A的所有属性和方法。
除了对象的原型,Object.create方法还可以接受第二个参数。该参数是一个属性描述对象,它所描述的对象属性,会添加到新对象。

var o = Object.create({}, {
  p1: { value: 123, enumerable: true },
  p2: { value: 'abc', enumerable: true }
});

// 等同于
var o = Object.create({});
o.p1 = 123;
o.p2 = 'abc';

此外,Object.create方法生成的对象,继承了它的原型对象的构造函数。

function A() {}
var a = new A();
var b = Object.create(a);

b.constructor === A // true
b instanceof A // true

实际上,如果老浏览器不支持Object.create方法,可以用以下代码自己部署:

if (typeof Object.create !== 'function') {
  Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
  };
}

上述代码表示,Object.create方法实质是新建一个构造函数F,然后让Fprototype属性指向作为原型的对象o(这个o是带输入的参数),最后返回一个F的实例。整体来看,这就实现了Object.create的功能:接收一个对象作为参数(原型对象),同时返回一个新对象(实例对象)`
以下三种方式生成新的对象时等价的:

var o3 = new Object();
var o1 = Object.create({});
var o2 = Object.create(Object.prototype);

Object.create方法生成的新对象,动态继承了原型。在原型上添加或者修改任何方法,会立刻反应在子对象之上。

var o1 = { p: 1 };
var o2 = Object.create(o1);
var o3 = Object.create(o1);

console.log(o3.p);//1
console.log(o2.p);//1
o1.p = 2;
console.log(o1.p);//2
console.log(o2.p);//2
console.log(o3.p);//2
二、Object.prototype.isPrototypeOf()方法

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.isPrototypeOf({}) // true
Object.prototype.isPrototypeOf([]) // true
Object.prototype.isPrototypeOf(/xyz/) // true
Object.prototype.isPrototypeOf(Object.create(null)) // false

上面代码中,由于Object.prototype处于原型链的最顶端,所以对各种实例都返回true,只有继承null的对象除外。

三、Object.prototype.__proto__

__proto__属性(前后各两个下划线)可以改写某个对象的原型对象。

var obj = {};
var p = {};

obj.__proto__ = p;
Object.getPrototypeOf(obj) === p // true

上面代码通过__proto__属性,将p对象设为obj对象的原型。

根据语言标准,__proto__属性只有浏览器才需要部署,其他环境可以没有这个属性,而且前后的两根下划线,表示它本质是一个内部属性,不应该对使用者暴露。因此,应该尽量少用这个属性,而是用Object.getPrototypeof()(读取)和Object.setPrototypeOf()(设置),进行原型对象的读写操作。此外,还可以使用Object.getPrototypeOf方法,检查浏览器是否支持__proto__属性,老式浏览器不支持这个属性。

Object.getPrototypeOf({ __proto__: null }) === null

上面代码将一个对象的__proto__属性设为null,然后使用Object.getPrototypeOf方法获取这个对象的原型,判断是否等于null。如果当前环境支持__proto__属性,两者的比较结果应该是true。

Object.getPrototypeOf()方法
Object.getPrototypeOf()方法返回一个对象的原型。这是获取原型对象的标准方法。
Object.getPrototypeOf(Object.prototype)// null

通过这个例子,我们可以看出来,最顶层的原型对象——Object.prototype对象,其原型是null,由于null没有任何属性,所以原型链到此为止。如果想要生成一个不继承任何属性(比如没有toStringvalueOf方法)的对象,可以将Object.create的参数设置为null

var o = Object.create(null);
o.valueOf()
// TypeError: Object [object Object] has no method 'valueOf'

上面代码表示,如果对象o的原型是null,它就不具备一些定义在Object.prototype对象上面的属性,比如valueOf方法。
下面代码展示了空对象、函数对象以及以F为构造函数的实例对象f,它们的原型对象

// 空对象的原型是Object.prototype
Object.getPrototypeOf({}) === Object.prototype// true
// 函数的原型是Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype// true
// f 为 F 的实例对象,则 f 的原型是 F.prototype
var f = new F();
Object.getPrototypeOf(f) === F.prototype// true
四、Object.setPrototypeOf()方法

Object.setPrototypeOf()方法可以为现有对象设置原型,返回一个新对象。
Object.setPrototypeOf()方法接收两个参数,第一个是现有对象,第二个是新设置的原型对象。

var a = {x: 1};
var b = Object.setPrototypeOf({}, a);
// 等同于
// var b = {__proto__: a};
b.x // 1

上面代码中,b对象是Object.setPrototypeOf方法返回的一个新对象。该对象本身为空、原型为a对象,所以b对象可以拿到a对象的所有属性和方法。b对象本身并没有x属性,但是JavaScript引擎找到它的原型对象a,然后读取ax属性。

new命令通过构造函数新建实例对象,实质就是将实例对象的原型,指向构造函数的prototype属性,然后在实例对象上执行构造函数。

var F = function () {
  this.foo = 'bar';
};

var f = new F();

// 等同于
var f = Object.setPrototypeOf({}, F.prototype);
F.call(f);

Reference:

参考自:JavaScript中prototype用法 - jasonzds的博客 - CSDN博客

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值