深入解析javascript原型链

首先我们要弄清楚几个概念:


一、函数对象和普通对象

我们定义的function,其实是Function对象的一个实例,如:function a(name){this.name=name}相当于var a=new Function('name','this.name=name');

每个函数对象都prototype属性,通过它可以实现原型继承。

由new Object()生成的对象我们称之为普通对象,我们非常熟悉的json变量,其实是Object的一个实例,如:var person={name:'张三'},相当于var person=new Object(),person.name='张三'。普通对象没有prototype属性。


二、原型对象

我们定义了一个函数后,系统会自动为其加上prototype属性对象,可以在它上面添加属性和方法, 实例化后可以直接调用。

原型对象包含:

1、constructor:指向构造函数

2、可以自定义方法和属性。如fun.prototype.diyMethod=function(){}

3、__proto__:指向Object.prototype

var Person=function(){};
Person.prototype.say=function(){};
var onePerson=new Person();
onePerson.say();

 

三、原型继承

原型的设计使得javascrip具有面向对象编程的能力。通过原型赋值可以轻松实现继承。

var Person=function(){};
console.log(Person.toString());//A 输出'function(){}' 
Person.prototype.say=function(){};
Person.prototype.eat=function(){};
var Man=function(){};
Man.prototype=new Person();//B
Man.prototype.constructor=Man; //运行B后Man.prototype.constructor指向Person,需要把构成函数指向自己,虽然不影响C行调用Man构造函数进行实例化
Man.prototype.makeMoney=function(){};
var oneMan=new Man();//C
oneMan.say();
oneMan.eat();
oneMan.makeMoney();

Man可以调用Person的say,eat方法,并在此基础上扩展了makeMoney方法。这就是js通过原型实现继承。


 四、原型链

js每个对象都有一个__proto__属性,它指向创建实例的对象的prototype。当要方位对象的属性时,首先判断对象本身有没有,有的话执行,没有的话会到它的__proto__中找。

我们来分析下上例中的代码:

Person.toString():Person-->自己没有-->Person.__proto__-->Function.prototype-->没有-->Function.prototype.__proto__-->Object.prototype-->toString()

oneMan.say():oneMan-->自己没有-->oneMan.__proto__-->Man.prototype-->new Person()-->自己没有-->new Person().__proto__-->Person.prototype-->say()

oneMan.makeMoney():oneMan-->自己没有-->oneMan.__proto__-->Man.prototype-->makeMoney()

可以看出原型都是通过__proto__来传递的,形成原型链。

下面是一张我自己画的原型链的关系图



可以看出,js中任何对象都由Object.prototype产生的。


五、Objec和Function的关系

Function.__proto__===Function.prototype true

Function.prototype.__proto__===Object.prototype true

Object.__proto__===Function.prototype true


Function instanceof Function true

Function.prototype instanceof Object true

Object instanceof Function true


可以看出Function、Function.prototype都是Object实例,Object又是Function的实例。看似有点你中有我我中有你的感觉。那到底是先有Function还是先有Object呢?

实际上几者的关系是:

Object.prototype-->Function.prototype-->Function-->function

Object.prototype-->Function.prototype-->Object-->{}

所以Function和Object没有先后关系,只是它们都是由Object.prototype产生,它在原型链的顶端,然后各自产生函数对象和普通对象


六、instanceof

用于判断左边是否为右边的实例,遵循一个规则:只要左边对象__proto__==右边对象prototype,则返回true

如:Function.prototype.__proto__===Object.prototype 

Function instanceof Object true

Function.prototype instanceof Object true


七、不用new关键字实现对象实例化

理解了原型链后其实我们可以不用new就可以获得实例对象,原理就是手动对__proto__赋值

var Person=function(){};
console.log(Person.toString());//A 输出'function(){}' 
Person.prototype.say=function(){};
Person.prototype.eat=function(){};
var Man=function(){};
Man.__proto__=Person.prototype;
Man.makeMoney=function(){};
Man.say();
Man.eat();
Man.makeMoney();
不过有些浏览器不支持手动修改对象的__proto__属性,为了兼容性建议大家使用传统的new方法实例化对象


讲的不对的对方欢迎大家指出,如果觉得对自己有帮助记得点个赞哦^_^

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值