JavaScript深入理解之原型

2017-01-09 14:07:54来源:网络收集作者:三线码农人点击

JavaScript深入理解之原型

JavaScript中所有的对象都有一个特殊的内置属性-prototype,该属性是对其它对象的引用,我们通常所说的原型指的就是原型属性prototype,下面以函数对象为例,进行说明。


1.原型属性
* 函数的初始prototype属性值为一个‘空’对象 *


function Foo() {
return 123;
}
console.dir(typeof Foo.prototype);// => 'object'
foo.prototype = {a: 123};
console.log(Foo.prototype.a) // => '123'

* 也可以设置prototype属性,这个不会对foo函数本身造成影响,因为只有当foo()作为构造器使用时,这些属性才会起作用。 *


2.利用原型添加方法和属性
* 构造函数.prototype.属性名 = 属性值 *


function Foo() {
this.a = 123;
this.b = 456;
}
Foo.prototype.c = 789;

3.使用原型的方法和属性


function Foo() {
this.a = 123;
this.b = 456;
}
Foo.prototype.c = 789;
let AA = new Foo(); // a、b是AA的自身属性,c是其原型属性
Foo.prototype.d = 135;// d是原型属性
let BB = new Foo();
console.log(AA.a);// => 123
console.log(AA.c);// => 789
console.log(AA.d);// => 135
console.log(BB.d)// => 135
console.log(AA.constructor.prototype);// => {c:789, d:135}
console.log(AA.constructor.prototype === BB.constructor.prototype)// true

* 上例中:开始给构造函数Foo增加了原型属性c,新建对象AA,aa有a、b、c三个属性,之后给Foo再次增加原型属性d,又新建一个对象BB,AA和BB都具有d属性,因为原型具有‘实时’性,又AA和BB是基于同一个构造对象创建的,所以AA和BB都能够访问到d属性。访问对象的某个属性时,JS引擎会先查找自身属性,如果没有,会查找构造器函数的原型属性 *


4.判断当前对象是否是另一个对象的原型 —– isPrototypeOf()


let aa = {a: 123};
function Foo() {
}
Foo.prototype= aa;
let AA = new Foo();
let rest = aa.isPrototypeOf(AA);
console.log(rest);// => true

5.关于proto


function Foo() {
this.a = 123;
this.b = 456;
}
Foo.prototype.c = 789;
let AA = new Foo();
let bb = AA.__proto__;
let cc = AA.constructor.prototype;
let dd = AA.constructor;
console.log(bb);// => {c: 789}
console.log(cc);// => {c: 789}
console.log(bb === cc);// => true
console.log(dd);// => Foo
proto是实例对象的属性
prototype是构造函数的属性
constructor是实例对象的属性
proto指向该实例对象基于的构造函数的原型属性
prototype是构造函数的原型属性
constructor指向该实例对象基于的构造函数

6.扩展内建对象属性


String.prototype.resver = function() {
return 123;
}
console.log('456'.resver());// => 123

* 利用prototype来扩展内建对象属性 *


7.原型陷阱


function Foo() {
this.a = 123;
}
Foo.prototype.b = 456;
let AA = new Foo();
console.dir(AA.constructor); // => Foo
console.dir(AA.__proto__); // => {b: 456}
Foo.prototype = {//重写构造函数原型属性
c: 789,
d: 135
}
// 重写构造函数原型属性后,重写之前的对象__prototype__指向的依旧是旧的原型属性
console.dir(AA.c);// => undefined
console.dir(AA.b);// => 456
console.dir(AA.__proto__); // => {b: 456}
let BB = new Foo();
/* 重写构造函数原型属性后,新建的对象实际上不是基于原来的构造函数了,看下面第三个打印,新建对象的__proto__属性指向的是新的原型属性,即是新的构造函数(新建对象基于该构造函数)的原型属性 */
console.dir(BB.c);// => 789
console.dir(BB.b);// => undefined
console.dir(BB.constructor); // => Object
console.dir(BB.__proto__); // => {c: 789, d: 135}
}

* 重写某个对象的prototype时,需要重置相应的constructor属性 *

最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台