JavaScript深入理解之原型

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属性 *

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值