var obj = function () {
this.name = "test";
this.age = "100";
}
obj.prototype = function{
var a="覆盖后的函数";
};
var o = new obj();
document.writeln(o.constructor);
this.name = "test";
this.age = "100";
}
obj.prototype = function{
var a="覆盖后的函数";
};
var o = new obj();
document.writeln(o.constructor);
prototype就是个属性.
看调试器最清楚了。
toString方法在原型prototype上,你重新给obj函数prototype赋值后,obj函数原型上没有了toString方法,根据原型链机制,将从其原型的原型上查找该方法,所以调用了其基类Object类的toString方法
obj.prototype = {
toString:function(){ alert('楼上的回答很强悍'); }
};//
var obj = function () {
this.name = "test";
this.age = "100";
}
obj.prototype = {
constructor:obj
};//有时候 你看到的就是因
(1)
代码稍作改动,如下:var obj = function () {
this.name = "test";
this.age = "100";
}
//给原型随便加上一个属性foo(原型为空的时候,控制台显示出的对象结构不完整)
obj.prototype = {
foo: function(){}
};
var o = new obj();
//用console.log直接在控制台输出(在浏览器原型链之类的是无法正常输出的)
console.log(o)
最终,控制台输出的对象o如下:
(2)
首先应该知道的是:在实例化之后,实例化对象中会有一个__proto__属性,这个属性的值便是原型对象;在上面的代码里就是:"原型对象=obj.prototype=o.__proto__={ foo:function(){} }"。
其次:在实例化之后,当读取实例化对象的某个属性时:会先在对象身上找这个属性,如果找不到再到原型对象里找。结合上面的图:当你读取o.constructor属性时,首先在o中在找,显然o自身的属性只有name和age,所以到o的原型对象即:o.__proto__中继续找;
因为原型对象也是对象,所以寻找属性也会遵循“先自身后原型”的方法,因此会先在o的原型对象本身找constructor,显然原型对象自身只有foo这么一个属性,所以继续到原型对象的原型对象(有点绕)中找,即图中的“o.__proto__.__proto__”,结果如图所示找到了!所以最终显示的值如楼主所见。PS: __proto__虽然在控制台中的显示与对象的自身属性并无两样,但是严格来讲它并不是对象自身的属性,它只是用来将对象和原型对象联系起来的一个桥梁,只在底层操作中会用到。
function obj(){
//...
};
var o = new obj();
相信这样的代码大家都经常写, 按照我们的传统面向对象语言(C#, java等), 这叫做new了一个obj类.
但是在js中又没有什么class关键字, 叫起来好像有点怪怪的, 于是更常见的是称呼obj是一个类构造函数.
不过其实在javascript中吧, obj其实就是一个Object, 一个很特殊的Object.
这货与new出来的对象o之间的区别在哪里呢?区别就在于function定义的对象有一个prototype属性,
而这个prototype属性中呢又有一个constructor属性, 这个属性就指向obj函数本身。
(好吧, A爱着B, 而B又爱着C, 剧终才发现C原来就是A - - )那么new一个对象时又发生了什么呢?
其实 var o = new obj() 可以拆成这几步:
var o={} //创建一个新对象o
obj.call(o) //o作为this参数调用构造函数obj, 喏, 这样你赋值的name, age都赋值给新对象o.
还有一个很重要的一步,我把它放到最后来说了(它发生在创建新对象o的后面):
任何一个对象, 都有一个属性名叫__proto__, 我们称之为内置原型对象,(当然, 你可别把它和prototype混淆了)
紧接在新创建对象后, o就被设置为了obj.prototype的值.话说, 到了这里, 你应该能明白你的问题了吧?
在你未设置obj.prototype之前:
function obj(){
//...
}
var o = new obj();
alert(o.constructor);
喏: alert(o.constructor) --> alert(o.__proto__.constructor) --> alert(obj.prototype.constructor) --> alert(obj) --> alert(obj.toString())
发现了吧, 调用的是obj函数的toString方法, 函数的toString方法会输出该方法的代码
那么在你设置obj.prototype之后呢?
function obj(){
//...
}
obj.prototype={}
var o = new obj();
alert(o.constructor);
显然可以看到, 你把obj.prototype给赋值成了一个新对象, 而且还是个空的新对象, 那么此时此刻会发生什么呢?
我们不难想到, o在找constructor的时候找到的是Object.constructor:
o.constructor --> o.__proto__.constructor --> obj.prototype.constructor --> {}.constructor --> {}.prototype.constructor --> Object
最终,输出了Object的构造函数。嗯,你看,其实一点也不复杂,一点也不难理解,就是这么简单。。嗯唔~~
(PS: By the way, 我发现这是我在CSDN回复过的有史以来最长的帖, 哈哈哈)
紧接在新创建对象后, o就被设置为了obj.prototype的值.
我是想说o.__proto__就被设置为了obj.prototype的值.太粗糙了,咳。。
既然有哥们专门引用这段了,我就再补充点吧:
好吧,我想想, 应该用这样的伪代码来描述一下 new obj():
function obj(){
// var tmp={}; //new 操作符会创建一个新对象
// this = tmp; //这个函数的this指针被设置为该新对象
this.name="xxx"; //用this添加属性的语句, 都赋值到了这个新对象中
this.age="ooo";
//return tmp; //如果没有显式的return语句, 那么将返回这个新对象
}var o = new obj(); //o 被设置为这个新对象其中要说明的是, 如果obj有显式的return语句, 那么也必须是return 一个对象才是有效的, 比如看:
function obj(){
return 2; //返回数字字面值 2
}var x = new obj();
可以试试看, 返回的是什么?
返回的其实是一个空对象, 而不是2:
function obj(){
// var tmp={}; //new 操作符会创建一个新对象
// this = tmp; //这个函数的this指针被设置为该新对象
return 2; //显式返回的不是一个对象, 该语句无效
//return tmp; //返回这个新对象
}OK, 写完了, 希望没有误人子弟..
其实这个比想的更简单,首先 对象o自身没有o.constructor属性,
故根据原型机制,o.constructor===o.prototype.constructor;而o.prototype===obj.prototype==={}
而显然{}的构造函数是Object,
故最终o.constructor===({}).constructor===Object