标签:
在《关于思维方式的思绪》那篇文章里提到了,
原型的本质就是一种委托关系。
即我这里没有,就到我的原型里去看看,一旦找到就当成我的用。
本文详细说一下这个事情。
比如某女买东西,钱都是她老公付款的。
用程序刻画是这样的:
1 var girl = { 2 name:‘小美‘ 3 }; 4 var boy = { 5 name:‘小帅‘, 6 pay:function(){ 7 console.log(‘花了1000元‘); 8 } 9 }; 10 Object.setPrototypeOf(girl,boy); 11 girl.pay();
/**
程序中指明了girl的原型是boy, girl 没有pay方法, 但是boy有, 所以boy花钱了.
从这个例子来看,原型是一种委托关系,如果说是一种继承关系就不是那么贴切了.
*/
1 var girl0 = { 2 name: ‘小美‘, 3 pay:function(){ 4 boy0.pay(); 5 } 6 }; 7 8 var boy0 = { 9 name: ‘小帅‘, 10 pay:function(){ 11 console.log(‘花了2000元‘); 12 } 13 } 14 girl0.pay();
同上面代码意义相同
1 /** 2 用这种委托关系,而不是用继承关系去理解原型,会感觉一切豁然开阔. 3 下面我们通过这个例子看看什么事原型链? 4 */ 5 var a = { 6 fn1:function(){ 7 console.log(1); 8 } 9 }; 10 var b = { 11 fn2:function(){ 12 console.log(2); 13 } 14 }; 15 var c = { 16 fn3:function(){ 17 console.log(3); 18 } 19 }; 20 var d = { 21 fn4:function(){ 22 console.log(4); 23 } 24 }; 25 Object.setPrototypeOf(d,c); 26 Object.setPrototypeOf(c,b); 27 Object.setPrototypeOf(b,a); 28 d.fn1(); 29 d.fn2(); 30 d.fn3(); 31 d.fn4(); 32 /** 33 上面代码中,a是b的原型,b是c的原型,c是d的原型. 34 那么d要找到fn1方法,怎么找呢? 35 先去其原型c中找.==没找到 36 再去c的原型b中找.==没找到 37 再去b的原型a中找.==找到了 38 因此能调用fn1的方法. 39 上面的过程就是原型链查找的过程. 40 讲到这里,原型链的原理想必是懂了. 41 此时我们再看a,b,c,d四个对象是什么关系? 42 如果要看作是集成的话,那么就是父子关系. 43 如果用委托的观点来看,那么每一个对象,都是后一个对象的智囊,也就是原型. 44 所以本文的关点是什么呢? 45 不要把原型当成亲爹,要当成智囊,要当成老公,要当成干爹. 46 本质是委托关系,说白了,就是利用. 47 其实,讲到这里原型是什么已经基本说完,后面我们准备展开说说,跟构造函数扯上. 48 */
第一个问题:什么叫做"一旦找到就当我的用"?
其实指的就是this问题.
1 var aaa = { 2 sayName:function(){ 3 console.log(this.name); 4 } 5 }; 6 var laoyao = { 7 name:‘laoyao‘ 8 }; 9 Object.setPrototypeOf(laoyao,aaa); 10 laoyao.sayName();
第二个问题:克隆的观点?
加入一个对象是一个空对象的原型.
因为空对象什么都没有,所有的都来自其原型,我们可以认为此对象是其原型的克隆.
1 var laowang = { 2 name:‘laowang‘, 3 sayName:function(){ 4 console.log(this.name); 5 } 6 }; 7 var fenshen={}; 8 Object.setPrototypeOf(fenshen,laowang); 9 console.log(fenshen.name); 10 fenshen.sayName();
当然, Object.create更适合描述克隆.
var laoli = { name:‘laoli‘, sayName:function(){ console.log(this.name); } }; var clone = Object.create(laoli); clone.sayName();
第三:我们封装产生对象的过程?
希望上述对象通过函数产生.
var createPerson = function(name){ return{ name:name, sayName:function(){ console.log(this.name); } }; } var laozhang =createPerson(‘laozhang‘); laozhang.sayName();
我也换种方式来做:
1 var createPersonOther = function(name){ 2 var o = {}; 3 o.name = name; 4 var proto ={ 5 sayName:function(){ 6 console.log(this.name); 7 } 8 }; 9 Object.setPrototypeOf(o,proto); 10 return o; 11 } 12 var laoyang =createPersonOther(‘laoyang‘); 13 laoyang.sayName();
1 var createPerson =function(name){ 2 var o = {}; 3 o.name = name; 4 Object.setPrototypeOf(o,createPerson.proto); 5 return o; 6 } 7 createPerson.proto={ 8 sayName:function(){ 9 console.log(this.name); 10 } 11 }; 12 var laoyao =createPerson(‘laoyao‘); 13 laoyao.sayName();
写到这里,你会发现其实跟我们平常写的代码很像:
1 var Person = function(name){ 2 this.name=name; 3 } 4 Person.prototype = { 5 sayName:function(){ 6 console.log(this.name); 7 } 8 }; 9 var laoyaoq =new Person(‘laoyaoq‘); 10 laoyaoq.sayName();
我们来刻画一下new过程.我们假设new是一个函数,类似call和bind的那样的函数.
new Person(‘laoyaoq‘);我们换成Person.new(‘laoyao‘);
此函数定义如下:
1 Function.prototype.new = function (){ 2 var that = Object.create(this.prototype); 3 this.apply(that,arguments); 4 return that; 5 }; 6 7 var Person = function (name) { 8 this.name = name; 9 } 10 11 Person.prototype ={ 12 sayName:function(){ 13 console.log(this.name); 14 } 15 }; 16 var laoli = Person.new(‘laoli‘); 17 laoli.sayName();
其中这new函数,不是完整模拟new的(考虑返回值是否是对象).详细请看《js语言精粹》47页。其中this指向的是当前函数(Person)
如果上面的代码看不习惯的话,我们也可以发明如下的api:
myNew(Person, ‘laoli‘)
1 var myNew = function() { 2 var Constructor = [].shift.call(arguments); 3 var that = Object.create(Constructor.prototype); 4 Constructor.apply(that, arguments); 5 return that; 6 } 7 var Person = function(name) { 8 this.name = name; 9 } 10 Person.prototype = { 11 sayName: function() { 12 console.log(this.name); 13 } 14 }; 15 var laoyaoyao = myNew(Person, ‘laoyaoyao‘); 16 laoyaoyao.sayName();
说明:上述代码改编于《JS设计模式与开发实践》第20页.
如果读者没有其他什么面向对象语言基础,
那么看此文,会觉得new是一个封装委托关系的过程.
而不是什么模拟java,模拟不彻底啥的.
所以在我看来,那些号召不要使用new的文章,也未必正确.
最后说下:这个委托的观点,《你不知道的javascript》有更详细的介绍.
标签:
原文地址:http://www.cnblogs.com/liubeimeng/p/5798885.html