大家都说javascript中的每个对象都有prototype属性。那么我们来测试一下看看。
var person = {name:"spring"};
alert(person.prototype); //output undefined
咿,不对,为什么是undefined,刚还说每个对象都有prototype属性呢。为什么我这又没有呢?
var s = new String();
var x = new Number();
var y = new Boolean();
var a = new Array();
var p = new Object();
这些都点不出prototype属性。我发现“javascript中的每个对象都有prototype属性”这句话就是忽悠人的
然后我又一看,它们每个都有一个相同的东西,那就是“__proto__”属性,这个属性是用来追溯原形的。比如
字符串s.__proto__属性中就提供了string的所有方法,如indexof,split等。
再看alert(s.__proto__.__proto__==p.__proto__);//output true。这就很清楚了字符串等所有的对象都是继
承了object。
实例化的对象没有prototype属性,除了Function对象。
var f = new Function(); //创建一个匿名函数
console.log(f.prototype);//打印出了一个constructor和__proto__俩属性。
function test (){} //声明一个test函数
console.log(test.prototype);//和上面的一样打印出了一个constructor和__proto__俩属性,我想着就是function和其他所有对象不同的特别之处了。实例化Function对象是有prototype属性的,而实例化new test()是没有prototype属性的。
实例化对象没有prototype属性,但是基本类型是有的。比如String类型
String.prototype.add = function(str){
return this+str;
}
这样的话所有的字符串都会拥有add方法。
var str = "123".add("456"); //output "123456"
其他的类型如Number Object Boolean,Array都可以用prototype来拓展自己的方法,且是全局的,在任何地方都能引用。
看第一段代码
var Person = function(){
this.getName = function(){
alert(1);
}
}
Person.prototype = {
getName: function(){
alert(2);
}
}
var p = new Person();
p.getName();//output 1
以上代码alert出1.原形中的getName并不会覆盖person的私有方法。
如果想调用原形中的getName方法可以这样:Person.prototype.getName();//output 2
那么想想如果用p.prototype.getName();会怎么样?p.prototype是undefined,上面已经提过了。
不过倒是可以这么用p.__proto__.getName(); .__proto__属性在IE中是不向外暴露的,所以是不兼容的。而在FF和chrome中是可以正常使用,它的作用就是可以用来逐步向上追溯查询prototype原形的。Person.prototype这个prototype属性是向外暴露且可修改的。
再看第二段代码:
var Person = function(){
}
Person.prototype = {
getName: function(){
alert(2);
}
}
var p = new Person();
p.getName();
p.getAge();//error: Uncaught TypeError: undefined is not a function
1.看了这两段代码就很清楚的知道了,在第一段代码中person对象中如果存在属性getName,那么就不再继续往上找,直接调用自己的,然而在自己内部随便做什么操作,都不会改变prototype原形中的任何东西;无论new Person()多少个,prototype里的东西始终不发生改变,就那么一个。
2.如果不存在getAge(),就会到Person 原形中去找,如果没有,就会一直向上找到顶级父类object prototype,如果也没有getAge方法,就会报错。
还是想说说那句话,“javascript中的每个对象都有prototype属性”。于是乎我又去尝试:
var p = {
name:"spring"
};
p.prototype = {
getName: function(){
alert(this.name)
}
}
p.getName();//error: Uncaught TypeError: undefined is not a function
这种写法是错误的,很显荣prototype被当成了p对象的一个私有属性和name属性同级,而不是我们所说的prototype。
但我深深的相信每一个对象都有一个“__proto__”对象,请注意它和prototype的区别。