我说说我的理解吧 准备几个概念,引用类型值和原始类型值 我们知道var i = 1;申明的是变量i,且其值为原始值1,而var i = {}申明的是值为{}的引用对象,即i中存储的是{}对象的内存地址的指针引用。 那么我们再来看上面的代码: function show(s) { document.write(s + "<br/>"); } //定义一个类型 ClassA, function ClassA() { this.a=[]; } //定义一个类型 ClassB function ClassB() { this.b = function() { alert("ClassB");}; } //ClassB 以 ClassA 的对象为原型 ClassB.prototype = new ClassA(); //创建两个 ClassB 类型的对象 var ojb1 = new ClassB(); var ojb2 = new ClassB(); // ojb1.a.push("牛","人");//调用数组的原型方法 show(ojb2.a);这里只是通过对象的自身方法给对象的引用增加内容,而内存地址的指针引用并没有改变,但是我们这样做却会出现问题: function show(s) { document.write(s + "<br/>"); } //定义一个类型 ClassA, function ClassA() { this.a=function(i) { alert(i);};; } //定义一个类型 ClassB function ClassB() { this.b = function() { alert("ClassB");}; } //ClassB 以 ClassA 的对象为原型 ClassB.prototype = new ClassA(); //创建两个 ClassB 类型的对象 var ojb1 = new ClassB(); var ojb2 = new ClassB(); // ojb1.a = ["牛","人"];//调用数组的原型方法 show(ojb2.a);因为每当我们创建一个数组,内存都会为其分配一个存储空间,在这里["牛","人"]和ClassA中的a的空数组其实是不同的指针引用,因此修改无效。
谢谢上面的各位了! 一楼的问题我已径想明白了! var a = "高手啊"; var b = a; //则 a 与 b 各不相观, 它们用各自的内存空间。 var a = ['高','手','啊']; var b = a; //则 a ,b 只能算是个指针, 它们指向同一块内存空间。 // 即,下面就可以看出来! a.push("!","错"); alert(b); 现在 我最需要的是 理解 prototype 的实质。 比如#3楼 的问题.谢谢了!
var strOut=""; function Site(){};
//strOut+="\n"+"(Site.prototype.constructor === Site):"+(Site.prototype.constructor === Site); // true //strOut+="\n"+'"valueOf" in Site.prototype:'+("valueOf" in Site.prototype); for(var key in Site.prototype) { strOut+="\n"+"key:\t"+key+"value:\t"+Site.prototype[key]; }
alert(strOut);//这里的结果是:"" ,strOut==""; 可见用foreach 没有方法扫描出来! // //但是你看下面这句: var flag = ("valueOf" in Site.prototype); alert(flag);//这里输出是true , // 为什么?用foreach 没有方法扫描出来?
<script type="text/javascript"> function show(s) { document.write(s + "<br/>"); } //定义一个类型 ClassA, function ClassA() { this.a=[]; } //定义一个类型 ClassB function ClassB() { this.b = function() { alert("ClassB");}; //加上这一行代码 ClassA.call(this); } //ClassB 以 ClassA 的对象为原型 ClassB.prototype = new ClassA(); //创建两个 ClassB 类型的对象 var ojb1 = new ClassB(); var ojb2 = new ClassB(); // ojb1.a.push("牛","人"); show("ojb2中a的值:"+ojb2.a); show("ojb1中a的值:"+ojb1.a); </script> 希望对你有用............
居然还在纠结,你的问题在于对象的引用传递问题,并非在prototype上面,当然你得先清楚prototype的原理才会知道这问题是在于对象的传递上。。关于prototype的原理网上一搜一大箩,自己google吧。。 值传递的问题,我举个最简单的例子 var arr = [], a = arr, b = arr; a.push('a_push'); alert(b);很简单吧,如果看不明白,自己慢慢琢磨,有些事自己琢磨明白了才算真正明白的
var ojb1 = new ClassB(); var ojb2 = new ClassB();obj1和obj2对象里面都没有显式的声明属性a,这时候obj1.a 和 obj2.a 都是去prototype中找到的a,不同对象的prototype只有一个(不是每个对象内部包含一个自己的prototype).所以obj1.a.push(""),改变了obj1和obj2共同对应的prototype中的a。所以,obj2.a和obj1.a内容一样,本身就是同一个东西。 但是obj1.a=['xxx'],这个和push不一样,=表示为obj1显式的增加一个自己的属性,这个属性包含在obj1内部(跟obj2毫无关系),显式增加的属性优先级大于prototype,以后obj1.a就是自己的属性a,不会再去prototype中找了。 obj2.a还是去prototype中找。
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a="是谁啊?";
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();
//
ojb1.a="高手";
show(ojb2.a);
上面代码的结果是 :是谁啊?function show(s) {
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=[];
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();
//
ojb1.a.push("牛","人");
show(ojb2.a);
上面代码的结果是: 牛人为什么会有 这种的结果呢?
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=[];
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();ClassB.prototype={a:[]};
当定义一个B的实例时,如果没为这个实例指定a属性,那么这个实例的a属性将用类B原型中定义的a属性,这里的a属性是一个数组(数组也是一个对象),所以obj1和obj2的a属性指向了同一个数组。
你两块代码的逻辑不一样,假使你第二块的代码改为
obj1.a=['牛','人'];逻辑上和第一块差不多。再试试
prototype 作为一个构造 对象前基础对象。
即,任何一个对象构造前,都是 在变量 prototype 指向的对象上 进行添砖加瓦的。比如function show(s) {
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=[];
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();
//
ojb1.a.push("牛","人");
show(ojb2.a);
等价于:function show(s) {
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=[];
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
//ClassB.prototype = new ClassA(); 我删了这行,再加如下代码
//创建两个 ClassB 类型的对象
var obj_a = new ClassA(); var ojb1 = new ClassB();
var ojb2 = new ClassB();
for(var i in obj_a)
{
ojb1[i]=obj_a[i];
ojb2[i]=obj_a[i];
}
ojb1.a.push("牛","人");
show(ojb2.a);
高手们,请看看,上面两种方法,是不是等价的!
而如果直接ojb1.a="高手" 这样做的话他不是给原型链找到的值赋值,而是新建一个属性给ojb1。从而查找的时候直接找到这个对象的a,相当于覆盖了原型链的a。
至于什么是原型和原型链,请看看下面
http://www.csser.com/dev/52.html
准备几个概念,引用类型值和原始类型值
我们知道var i = 1;申明的是变量i,且其值为原始值1,而var i = {}申明的是值为{}的引用对象,即i中存储的是{}对象的内存地址的指针引用。
那么我们再来看上面的代码:
function show(s) {
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=[];
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();
//
ojb1.a.push("牛","人");//调用数组的原型方法
show(ojb2.a);这里只是通过对象的自身方法给对象的引用增加内容,而内存地址的指针引用并没有改变,但是我们这样做却会出现问题:
function show(s) {
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=function(i) { alert(i);};;
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();
//
ojb1.a = ["牛","人"];//调用数组的原型方法
show(ojb2.a);因为每当我们创建一个数组,内存都会为其分配一个存储空间,在这里["牛","人"]和ClassA中的a的空数组其实是不同的指针引用,因此修改无效。
一楼的问题我已径想明白了!
var a = "高手啊";
var b = a;
//则 a 与 b 各不相观, 它们用各自的内存空间。
var a = ['高','手','啊'];
var b = a;
//则 a ,b 只能算是个指针, 它们指向同一块内存空间。
// 即,下面就可以看出来!
a.push("!","错");
alert(b);
现在 我最需要的是 理解 prototype 的实质。 比如#3楼 的问题.谢谢了!
function Site(){};
//strOut+="\n"+"(Site.prototype.constructor === Site):"+(Site.prototype.constructor === Site); // true
//strOut+="\n"+'"valueOf" in Site.prototype:'+("valueOf" in Site.prototype);
for(var key in Site.prototype)
{
strOut+="\n"+"key:\t"+key+"value:\t"+Site.prototype[key];
}
alert(strOut);//这里的结果是:"" ,strOut==""; 可见用foreach 没有方法扫描出来!
//
//但是你看下面这句:
var flag = ("valueOf" in Site.prototype);
alert(flag);//这里输出是true ,
// 为什么?用foreach 没有方法扫描出来?
valueOf方法是Object的prototype方法。而你用in来查找会检索原型链中所有的属性(Site的Prototype最终也指向Object的prototype),直到最顶层,亦即是Object的prototype(所有类型的prototype最终指向Object的prototype)。而你上面for循环只是遍历Site的prototype,而没有进行原型链上的搜索。
你想看更具体的,请看以下文章。
http://www.cnblogs.com/RicCC/archive/2008/02/15/JavaScript-Object-Model-Execution-Model.html
希望对你有帮助
var str = "string";
var Fn = function() {var i;};
var f = new Fn();
//---------下面是结果 ,为什么?---------------------------------
str.__proto__===""
str.prototype===undefined
str.constructor===function String() { [native code] }
str.__proto__.constructor===function String() { [native code] }Fn.__proto__===function () { }
Fn.prototype===[object Object]
Fn.constructor===function Function() { [native code] }
Fn.__proto__===constructor:function Function() { [native code] }f.__proto__===[object Object]
f.prototype===undefined
f.constructor===function () { var i; }
f.__proto__.constructor===function () { var i; }主要的是 __proto__ 与 prototype 的区别!
function show(s) {
document.write(s + "<br/>");
}
//定义一个类型 ClassA,
function ClassA() {
this.a=[];
}
//定义一个类型 ClassB
function ClassB() {
this.b = function() { alert("ClassB");};
//加上这一行代码
ClassA.call(this);
}
//ClassB 以 ClassA 的对象为原型
ClassB.prototype = new ClassA();
//创建两个 ClassB 类型的对象
var ojb1 = new ClassB();
var ojb2 = new ClassB();
//
ojb1.a.push("牛","人");
show("ojb2中a的值:"+ojb2.a);
show("ojb1中a的值:"+ojb1.a);
</script>
希望对你有用............
值传递的问题,我举个最简单的例子 var arr = [],
a = arr,
b = arr;
a.push('a_push');
alert(b);很简单吧,如果看不明白,自己慢慢琢磨,有些事自己琢磨明白了才算真正明白的
__proto__
prototype
apply //this.base.apply(this, arguments);
call //this.base.call(this, m_elements.length);
至于 apply 和 call 你可以看看这文章
http://a48121905.blog.163.com/blog/static/187490265201110305295715/
[align=center]prototype.js 库:
jQuery 源码,
[/align]
终于明白 apply 和 call 了,
这两个是 借刀杀人 啊, 我在C++/C# 都没有看过这种 方法 啊 !!!
第一次见到!牛。
var ojb2 = new ClassB();obj1和obj2对象里面都没有显式的声明属性a,这时候obj1.a 和 obj2.a 都是去prototype中找到的a,不同对象的prototype只有一个(不是每个对象内部包含一个自己的prototype).所以obj1.a.push(""),改变了obj1和obj2共同对应的prototype中的a。所以,obj2.a和obj1.a内容一样,本身就是同一个东西。
但是obj1.a=['xxx'],这个和push不一样,=表示为obj1显式的增加一个自己的属性,这个属性包含在obj1内部(跟obj2毫无关系),显式增加的属性优先级大于prototype,以后obj1.a就是自己的属性a,不会再去prototype中找了。
obj2.a还是去prototype中找。