js函数prototype属性学习(二)
继续探讨js对象的prototype属性,前面已经看到在创建完一个对象之后,随时都会有一个_proto_属性伴随所有,那么,这个_proto_又是用来干嘛的,面试时问的高大上的原型链又是怎么回事?
拿出前面已经有的例子,如下:
function Person(name){
this.name = name;
this.interduceSelf= function(){
alert("my name is " + this.name);
};
};
Person.prototype.interduceSelfChinses = function(){
alert("我的名字是 " + this.name);
};
从这个例子可以看出,通过给person.prototype设置了一个函数对象的新方法,那有person实例(例中:person1)出来的普通对象就继承了这个新方法。接着看了下这两个东西:person1.__proto__和Person.prototype,截图如下:
二者压根就是同一个东西嘛,同时,我试验了person1.__proto__ == Person.prototype,结果为true,因此,我大胆推测构造函数new Person()发生时候的一个过程,
创建person1对象;
person1.__proto__ = Person.prototype;
Person.call('xiaoming');
同样,person.prototype对象也有__proto__属性,它指向创建它的函数对象(Object)的prototype;
person.prototype.__proto__ === Object.prototype //结果也还是 true
继续,Object.prototype对象也有__proto__属性,但它比较特殊,为null;
Object.prototype.__proto__; //结果为null
我们把这个由__proto__串起来的直到Object.prototype.__proto__为null的链叫做原型链,如下图:
__proto__按照定义来讲,是对象自带的一个属性,这个__proto__它本身又是一个对象,__proto__的属性,可以被person1读取到,但不会显示在person1对象里(是一个看起来对外隐身的属性),当然__proto__对象中的属性读取优先级要低于person1本身(一般视作隐秘属性,可以拿来用,但不必单独指定它)
而prototype呢,则是函数的一个自带属性,其中prototype又有两个元素,constructor和__proto__,
1、constructor指向函数本身;即
Person.prototype.constructor === Person //结果是true
Function.prototype.constructor === Function //结果是true
Object.prototype.constructor === Object //结果是true
2、__proto__指向的是创建它的那个对象的prototype,即
person1.__proto__ == Person.prototype //结果是true
构造函数在创建对象是最大的特点就是会把自身的prototype按值传递给被构造对象的__proto__,那么,在上面那段代码中,执行new Person()时,一下子指定了好几个对象的prototype和__proto__,请看如下的结构图:
由此可以做出如下总结:
1.原型和原型链是JS实现继承的一种模型,对对的,这么多看起来毫不相干的对象,通过原型、原型链,竟然给连成了亲家;
2.原型链的形成是真正是靠__proto__ 而非prototype,这点也毋庸置疑,从上面可以看出,整个链关系里,prototype充当的角色是连接点,而真正起绳索连接作用的却是__proto__。
看一个例子:
function code(){};
function javascript(){};
code.languageType = "interpreted language";
javascript.prototype = code;
var jquery = new javascript();
console.log(javascript.languageType) //结果是 undefined
console.log(jquery.languageType) // 结果是 interpreted language
不了解这个原型和原型链,还真有点丈二和尚摸不着头脑,现在来探讨一下:
javascript函数对象虽然指定了prototype属性是code,但它的__proto__内置属性却没有指定是谁,同时,原型链跟prototype属性八竿子打不着,而是依赖__proto__去查找,当然查找不到任何东西,因此,这里找不到languageType这个属性值;
jquery函数对象就不一样了,它在创建伊始就默认的指定了它的__proto__内置属性即为javascript.prototype,也即是code,code对象的languageType属性是有值的,也即是interpreted language,因此就读取到了属性值。