[英]difference between Prototype constructor and private property
考虑第一种情况:
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
问题:为什么我会得到不同的结果? 如果'this'指的是对象没有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”,但它们不包含。
首先检查单词原型的定义。 在考虑如何在JavaScript中创建新对象时,我认为记住这一点非常重要。
原型
名词
动词
原型是一个模型,将从中复制另一个表单。
当您在JavaScript中创建新对象时,这正是发生的事情。
var obj = new MyObject();
在上面的代码中,有很多事情会发生,但在问题的上下文中,有两件事情是相关的:
this
设置为新对象。 有了这些知识,让我们来看看你所描述的不同形式的设置变量:
function MyObject() {}
MyObject.myProperty = 'MyProperty';
了解函数本身是JavaScript中的对象非常重要。 因此, function MyObject
是自身的对象实例。 在第二行,我们在此函数对象上设置了属性myProperty
。
请参阅上面的创建步骤,您会注意到它不包括将函数对象的属性应用于新的实例对象。 它仅应用函数对象原型中的属性,然后使用this
set将函数体运行到新实例。
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>
为什么myVar没有功能? 如果它存储在对象原型中,则应该可以在f()中访问它。
它可以在函数中访问,但不能像f.myVar
那样f.myVar
,而是作为this.myVar
或f.prototype.myVar
。
为什么我会得到不同的结果? 如果'this'指的是对象没有f.myVar意味着在myObject中访问myVar?
函数f
与对象实例不同。 该函数是对象的构造函数,将其与new
关键字一起使用会创建一个与函数分离的实例。
使用f.var
,这是函数对象的属性var
。 在函数中使用this.var
时,即使用new
关键字创建的对象实例中的属性var
。
如果使用f.var
,这是构造函数对象的属性,那么即使您创建了对象的多个实例,它也将是同一个变量,并且只能使用f.var
访问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
分配一个值,这将使它成为对象实例中的属性。
例:
function f(value) {
this.var = value;
}
f.prototype.getValue = function(){
return this.var;
};
var instance1 = new f(42);
var instance2 = new f(0.01);
// now you have two instances with separate values:
console.log(instance1.getValue()); // shows "42"
console.log(instance2.getValue()); // shows "0.01"
至于编辑中的问题,真的很简单:-)
你有一个函数对象function f(){}
你添加到这个对象属性,就像你可以添加属性到javascript f.someVar = 1
任何其他对象
这与function f(){this.someVar = someValue;}
因为this
在javascript中取决于函数调用的方式,如果使用call
或apply
函数调用,则function f(){this.someVar = someValue;}
创建的对象,全局对象或其他内容。
使用new
运算符创建对象时 - 将f
作为构造函数调用,在这种情况下, this
内部函数引用创建的对象,并且函数内添加的所有属性作为this.something = val
添加到创建的对象。
注意:您不直接使用函数中的任何属性,因此不会将其添加到创建的对象中。
至于prototype
:当你创建对象时 - 你只需将创建对象的prototype
属性设置为f.prototype
对象。 所以在你创建对象的最后,你不要使用任何直接添加到函数对象的属性,只是原型和属性中的属性,在构造函数中手动添加this
属性
似乎你对功能和对象的原型感到困惑。
以下是Eloquent Javascript解释其差异的一句话:
重要的是要注意原型与构造函数关联的方式(通过其原型属性)与对象具有原型的方式(可以使用Object.getPrototypeOf检索)之间的区别。 构造函数的实际原型是Function.prototype,因为构造函数是函数。 它的原型属性将是通过它创建的实例的原型,但不是它自己的原型。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.