考虑第一种情况:
function f(){
console.log("inside the function : " + f.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
这是输出:
inside the function : undefined
from the object : 1
问题:为什么myVar在功能上无法使用?如果它存储在对象原型中,则应该可以在f()中访问。
现在这个场景:
function f(){
console.log("inside the function : " + this.myVar);
}
f.prototype.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
输出:
inside the function : 1
from the object : 1
问题:为什么我会得到不同的结果?如果'这个'是指对象并不是f.myVar意味着在myObject中访问myVar?
现在这个场景:
function f(){
console.log("inside the function : " + f.myVar);
console.log("inside the function using 'this' : " + this.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the object : " + myObject.myVar);
输出:
inside the function : 1
inside the function using 'this' : undefined
from the object : undefined
因此,如果我在不使用原型的情况下设置属性,它应该在实例化对象中可用。但如果我像这样编写脚本,它会产生一个奇怪的结果:
function f(){
console.log("inside the function : " + f.myVar);
}
f.myVar = 1;
var myObject = new f();
console.log("from the first object : " + myObject.myVar);
var strangeObject = myObject.constructor;
console.log("from the strange object : " + strangeObject.myVar);
输出:
inside the function : 1
from the first object : undefined
from the strange object : 1
" f.myVar"商店?那个变量是什么?我很困惑上面所有场景之间的区别。非常感谢完整的carification。
修改
主要问题是我不知道这究竟是什么意思:
function f(){}
f.someVar = someValue;
因为在其他语言中,函数是一个抽象概念,实际上在调用之前不存在。现在在JS中,默认情况下,函数是对象。好的,我上面的脚本应该有这样的对象:
{someVar : sameValue}
实际上我认为这应该与:
相同function f(){this.someVar = someValue;} //should create {someVar : someValue}
如果是这种情况,则通过调用" new f()"来实例化每个对象。必须包含这个" someVar"但他们没有。
答案 0 :(得分:2)
首先检查单词 prototype 的定义。在考虑如何在JavaScript中创建新对象时,我认为记住这一点非常重要。
<强>亲·到·类型强>
名词
动词
原型是一个模型,将从中复制另一个表单。
在JavaScript中创建新对象时,情况正是如此。
var obj = new MyObject();
在上面的代码中,有很多事情发生,但在问题的上下文中,有两件事情是相关的:
this
设置为新对象。考虑到这些知识,让我们来看看你所描述的不同形式的设置变量:
function MyObject() {}
MyObject.myProperty = 'MyProperty';
了解函数本身是JavaScript中的对象非常重要。因此,function MyObject
是自身的对象实例。在第二行,我们在此函数对象上设置了属性myProperty
。
请参阅上面的创建步骤,您会注意到它不包括将函数对象的属性应用于新的实例对象。它仅应用函数对象原型中的属性,然后运行函数体,并将this
设置为新实例。
function MyObject() {
this.myProperty = 'MyProperty';
}
此处,属性myProperty
已在单个实例上设置。
function MyObject() {}
MyObject.prototype.myProperty = 'MyProperty';
在此示例中,MyObject
的每个新实例都将被赋予其自己的名为myProperty
的属性,并将值设置为'MyProperty'
。从那里,每个实例都可以将自己的myProperty
更改为它所需的任何值,而不会影响另一个。
function MyObject() {
console.log('myProperty', this.myProperty); //Will output 'Outside constructor.'
this.myProperty = 'Inside constructor.';
console.log('myProperty', this.myProperty); //Will output 'Inside constructor.
}
MyObject.prototype.myProperty = 'Outside constructor.';
上面的示例显示了如何首先从原型应用myProperty
,然后在运行的函数中应用值覆盖。
让我们看看你提到的所有表格的例子:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2'),
output3 = document.getElementById('output3');
function MyObject(myProperty) {
this.myProperty = myProperty;
}
MyObject.myProperty = 'Function property.';
MyObject.prototype.myProperty = 'Prototype property.';
var obj = new MyObject('Constructor property');
output1.innerHTML = obj.myProperty;
output2.innerHTML = MyObject.myProperty;
output3.innerHTML = MyObject.prototype.myProperty;
<div id="output1"></div>
<div id="output2"></div>
<div id="output3"></div>
在上面的示例中,您将看到如何引用每个。现在仔细研究一下。看看从两个不同的对象实例设置的'Function属性'会发生什么:
var output1 = document.getElementById('output1'),
output2 = document.getElementById('output2');
function MyObject() {
//We are concatenating a string to the end of the property on each function call.
MyObject.myProperty += ' test ';
}
MyObject.myProperty = 'Function property.';
var obj1 = new MyObject();
var obj2 = new MyObject();
output1.innerHTML = MyObject.myProperty;
output2.innerHTML = MyObject.myProperty;
<div id="output1"></div>
<div id="output2"></div>
上面的代码演示了如何有效地共享函数级属性。那是因为它不是每个实例的一部分。它是功能对象的一部分。
在这里,我将向您展示使用new
运算符进行的过程,而不实际使用new
运算符:
var output = document.getElementById('output');
//Let's have an object that has a prototype property with some properties:
var MyPrototypeObject = {
prototype: {
myPrototypeProperty: 'Prototype property'
}
};
//Let's specify a function that will be used as a constructor:
function MyConstructorFunction() {
this.myInstanceProperty = 'Instance property';
}
//First, new creates an object
var obj = {};
//Next, it applies all the properties from the prototype. We are using the MyPrototypeObject's prototype property for this example
for (var key in MyPrototypeObject.prototype) {
var val = MyPrototypeObject.prototype[key];
//Set the same property on the new object.
obj[key] = val;
}
//Now the prototype has been applied, let's apply the constructor function that was called.
MyConstructorFunction.call(obj); //This calls MyConstructorFunction with this set to obj.
output.innerHTML = 'myPrototypeProperty: ' + obj.myPrototypeProperty + '<br>' + 'myInstanceProperty: ' + obj.myInstanceProperty;
<div id="output"></div>
答案 1 :(得分:1)
为什么myVar在功能上无法使用?如果它存储在对象中 原型应该可以在f()中访问。
可以在函数中访问,但不能f.myVar
,而是this.myVar
或f.prototype.myVar
。
为什么我会得到不同的结果?如果&#39;这个&#39;是指对象 不知道f.myVar意味着在myObject中访问myVar吗?
函数f
与对象实例不同。该函数是对象的构造函数,并使用new
关键字创建一个与函数分开的对象的实例。
使用f.var
时,即函数对象的属性var
。在函数中使用this.var
时,对象实例中的属性var
表示使用了new
关键字。
如果使用f.var
,这是构造函数对象的属性,那么即使您创建了对象的多个实例,它也将是同一个变量,并且只能使用{{{{}}进行访问。 1}}。
如果使用f.var
,那么它也将是对象的所有实例都相同的变量,但也可以使用f.prototype.var
访问该变量,因为对象继承了原型的成员
示例:
this.var
如果您想要一个对象的每个实例都是本地变量,那么您应该不使用这些变量。您应该为function f() {
console.log(f.var); // shows "42"
console.log(f.prototype.var); // shows "0.01"
console.log(this.var); shows "0.01";
}
f.var = 42;
f.prototype.var = 0.01;
分配一个值,这将使其成为对象实例中的属性。
示例:
this.var
答案 2 :(得分:0)
至于编辑中的问题,真的很简单: - )
你有一个功能对象function f(){}
您添加到此对象属性,就像您可以在javascript f.someVar = 1
这与function f(){this.someVar = someValue;}
不同,因为javascript中的this
取决于函数调用的方式,如果使用call
或{{1调用,则可以引用创建的对象,全局对象或其他内容功能。
当您使用apply
运算符创建对象时 - 您将new
作为构造函数调用,在这种情况下,f
内部函数将引用创建的对象,并且所有属性在函数内添加为{{ 1}}添加到创建的对象。
注意:您不直接使用函数中的任何属性,因此不会将其添加到创建的对象中。
至于this
:当你创建对象时 - 你只需将创建对象的this.something = val
属性设置为prototype
对象。所以在你创建对象的最后,你不要使用任何直接添加到函数对象的属性,只需要在构造函数中手动添加到prototype
的原型和属性中的属性
答案 3 :(得分:0)
似乎你对功能和对象的原型感到困惑。
以下是Eloquent Javascript解释差异的书的引用:
重要的是要注意原型的方式之间的区别 与构造函数关联(通过其prototype属性)和 方式对象有一个原型(可以使用 Object.getPrototypeOf)。构造函数的实际原型是 Function.prototype,因为构造函数是函数。它的原型 属性将是通过它创建的实例的原型,但是 不是它自己的原型。