我正在努力更好地掌握javascript类的内容和原因。具体来说,我试图理解为原型分配方法与在构造函数中使用this.methodName = function ...语句之间的区别。所以,我做了一个实验:
function CThis(){
this.method= function() {
console.log("method of ",this);
};
}
function CProto(){
}
CProto.prototype.method = function() {
console.log("method of ",this);
};
window.onload = function(){
ct = new CThis();
ct.method();
cp = new CProto();
cp.method();
};
我的假设是两者的行为方式相同,但我学到了一些东西。这是输出:
"method of " Object { method: CThis/this.method() } oop.js:3:4
"method of " Object { } oop.js:11:2
在构造函数中使用this.method实际上给了我一个典型oop程序中类的实例所需要的行为:即“this”指的是类实例。使用原型方法,似乎这是一个空对象。
我想这里的问题有三个:
提前致谢!
--- --- EDIT
我对此有了更多的想法,并意识到将示例扩展到单一方法之后可能是值得的,并尝试查看哪些变量可以访问。
function CThis(){
this.localthis = "I'm this.localthis";
var localvar = "I'm localvar";
this.method= function() {
console.log("method of ",this);
console.log("value of this.localthis:", this.localthis);
console.log("value of localvar with this.:", this.localvar);
console.log("value of localvar without this.:", localvar);
};
}
function CProto(){
this.localthis = "I'm this.localthis";
var localvar = "I'm localvar";
}
CProto.prototype.method = function() {
console.log("method of ",this);
console.log("value of this.localthis:", this.localthis);
console.log("value of localvar with this.:", this.localvar);
console.log("value of localvar without this.:", localvar);
};
window.onload = function(){
ct = new CThis();
ct.method();
cp = new CProto();
cp.method();
};
新输出:
method of " Object { localthis: "I'm this.localthis", method: CThis/this.method() } oop.js:5:4
"value of this.localthis:" "I'm this.localthis" oop.js:6:4
"value of localvar with this.:" undefined oop.js:7:4
"value of localvar without this.:" "I'm localvar" oop.js:8:4
"method of " Object { localthis: "I'm this.localthis" } oop.js:18:2
"value of this.localthis:" "I'm this.localthis" oop.js:19:2
"value of localvar with this.:" undefined oop.js:20:2
ReferenceError: localvar is not defined
因此在变量范围方面肯定存在差异(在this.method中,我可以从构造函数中访问var变量)。
答案 0 :(得分:0)
在第一种情况下,您创建的每个实例都有自己的方法副本,因此当您打印出对象时,它是可见的。每次调用构造函数时,JS引擎也可能必须对此函数执行编译步骤。
在第二种情况下,您创建的实例都没有任何属性。相反,当您调用该方法时,js引擎会在原型链中查找正确名称的属性。它查看cp.__proto__
并找到指向您所称为CProto.prototype
的对象的指针,该对象具有名为"方法"的属性。它可以打电话。
作为附加测试,将一个真实的实例变量添加到您的类中。将this.foo = 42;
添加到两个构造函数中,然后查看您获得的内容。
答案 1 :(得分:0)
首先,javascript OO是原型,因此它与基于类的OO不完全相同。你好像已经抓住了必要的部分。
Prototypical继承的工作方式有点像向后数据树:如果你没有在对象本身找到属性,看看它的原型,如果它不在它的原型上,看看它的原型是什么原型等等,直到没有原型。
<强> 1。什么是“this”指的是CProto.prototype.method里面的内容?
当调用 METHOD 时,它总是引用上下文对象(,即用于调用方法的对象)。
obj1.hello() // this === obj1
obj2.hello() // this === obj2
Object.getPrototypeOf(obj1).hello() // this is now global since you didn't use a contextual object.
obj1.hello.call(obj2) // this === obj2, because we forced a context change
<强> 2。关于在构造函数中使用对象的原型为函数分配函数,故事的其余部分是什么?
分配给原型会使原型的所有实例继承该方法。 在构造函数中分配意味着只有实例具有该方法。 否则,它基本上是相同的。实例方法的唯一优势是访问实例的私有上下文(闭包)。
在构造函数中分配时,对象本身就是方法的“所有者”。这会更改Object.key()
和for in
的工作方式。当它在Prototype上时,原型对象是“所有者”,因此您的实例对象没有将该方法作为自己的属性。这看似微不足道,但这是一个重要的区别,特别是在循环/循环对象属性时。
当您通过原型进行分配时,只有一个方法实例(它位于原型上)。当您通过构造函数分配时,您将为每个实例创建新上下文和新函数。虽然微不足道,但存在性能差异。
第3 强>
上面两个答案几乎解释了。