JavaScript编程中实现对象封装特性的实例讲解(2)

举例来说,如果让某个函数的prototype属性指向一个数组,就意味着该函数可以用作数组的构造函数,因为它生成的实例对象都可以通过prototype属性调用数组方法。

function MyArray (){} MyArray.prototype = new Array(); MyArray.prototype.constructor = MyArray; var mine = new MyArray(); mine.push(1, 2, 3); mine.length // 3 mine instanceof Array // true

上面代码的mine是MyArray的实例对象,由于MyArray的prototype属性指向一个数组,使得mine可以调用数组方法(这些方法其实定义在数组的prototype对象上面)。至于最后那行instanceof表达式,我们知道instanceof运算符用来比较一个对象是否为某个构造函数的实例,最后一行表示mine为Array的实例。

mine instanceof Array // 等同于 (Array === MyArray.prototype.constructor) || (Array === Array.prototype.constructor) || (Array === Object.prototype.constructor )

上面代码说明了instanceof运算符的实质,它依次与实例对象的所有原型对象的constructor属性(关于该属性的介绍,请看下一节)进行比较,只要有一个符合就返回true,否则返回false。

1.4 constructor属性
prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。

function P() {} P.prototype.constructor === P // true

由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。

function P() {} var p = new P(); p.constructor // function P() {} p.constructor === P.prototype.constructor // true p.hasOwnProperty('constructor') // false

上面代码表示p是构造函数P的实例对象,但是p自身没有contructor属性,该属性其实是读取原型链上面的P.prototype.constructor属性。

constructor属性的作用是分辨prototype对象到底定义在哪个构造函数上面。

function F(){}; var f = new F(); f.constructor === F // true f.constructor === RegExp // false

上面代码表示,使用constructor属性,确定变量f的构造函数是F,而不是RegExp。

2.Object.getPrototypeOf方法
Object.getPrototypeOf方法返回一个对象的原型。

// 空对象的原型是Object.prototype Object.getPrototypeOf({}) === Object.prototype // true // 函数的原型是Function.prototype function f() {} Object.getPrototypeOf(f) === Function.prototype // true // 假定F为构造函数,f为F的实例对象 // 那么,f的原型是F.prototype var f = new F(); Object.getPrototypeOf(f) === F.prototype // true

3.Object.create方法
Object.create方法用于生成新的对象,可以替代new命令。它接受一个对象作为参数,返回一个新对象,后者完全继承前者的属性,即前者成为后者的原型。

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

上面代码中,Object.create方法在o1的基础上生成了o2。此时,o1成了o2的原型,也就是说,o2继承了o1所有的属性的方法。

Object.create方法基本等同于下面的代码,如果老式浏览器不支持Object.create方法,可以用下面代码自己部署。

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

上面代码表示,Object.create方法实质是新建一个构造函数F,然后让F的prototype属性指向作为原型的对象o,最后返回一个F的实例,从而实现让实例继承o的属性。

下面三种方式生成的新对象是等价的。

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

如果想要生成一个不继承任何属性(比如toString和valueOf方法)的对象,可以将Object.create的参数设为null。

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

上面代码表示,如果对象o的原型是null,它就不具备一些定义在Object.prototype对象上面的属性,比如valueOf方法。

使用Object.create方法的时候,必须提供对象原型,否则会报错。

Object.create() // TypeError: Object prototype may only be an Object or null

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

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

上面代码表示,修改对象原型会影响到新生成的对象。

除了对象的原型,Object.create方法还可以接受第二个参数,表示描述属性的attributes对象,跟用在Object.defineProperties方法的格式是一样的。它所描述的对象属性,会添加到新对象。

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

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wzsdzs.html