首先我们要弄清楚几个概念:
一、函数对象和普通对象
我们定义的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方法实例化对象
讲的不对的对方欢迎大家指出,如果觉得对自己有帮助记得点个赞哦^_^