据我所知,函数应该从其prototype
对象继承属性,可以使用.prototype
或__proto__
属性访问该对象。
//my prototype Object
var myObj = {
a: 1,
b: 2
};
var myFunc = function () {};
// setting function's `prototype` property
myFunc.prototype = myObj;
alert(myFunc.a);
//returns undefined (Why???) I was expecting 1
但是当我尝试以下内容时,
//setting function __proto__ property
myFunc.__proto__ = myObj;
//returns 1
alert(myFunc.a);
那么为什么我设置myFunc.__proto__
而不是设置myFunc.prototype
时呢?
我确实参考了__proto__ VS. prototype in JavaScript,但无法弄清楚。
答案 0 :(得分:15)
<强> __proto__
强>
您实际上可以使用[[Prototype]]
访问对象的内部__proto__
属性。您可以将[[Prototype]]
视为继承层次结构中当前对象的实际父级。
<强> prototype
强>
这是一个特殊属性,在(构造函数)函数对象上设置时,用于为从构造函数创建的实例建立继承链。例如,
function Foo() {}
Foo.prototype = {a: 1};
现在,当您创建类型为Foo
的新对象时,新创建的对象的内部[[Prototype]]
属性将引用Foo.prototype
对象。您可以像这样确认
console.assert((new Foo()).__proto__ === Foo.prototype);
在你的情况下,
myFunc.prototype = myObj;
您正在函数对象上创建prototype
属性,只有在使用此函数(构造函数)创建新对象时才会使用此属性。您可能希望将其视为新对象的模板。因此,当你执行myFunc.a
时,JS引擎会尝试在a
中找到myFunc
及其原型链中的父项,但它找不到它,这就是它返回的原因{ {1}}。
但是,当你这样做时
undefined
您要将原型链中的myFunc.__proto__ = myObj;
的父级设置为myFunc
。因此,当你执行myObj
时,JS引擎首先尝试在myFunc.a
对象本身中找到a
,但它不在那里。因此,它试图在其直接父代中找到它,即myFunc
。这就是为什么在这种情况下它会返回myObj
。
注意:您可以使用以下函数更好地了解原型链
1
现在,让我们在将对象设置为函数对象的function printPrototypeChain(object) {
while (object !== null) {
console.log(object);
object = Object.getPrototypeOf(object);
}
}
属性时打印原型链。
prototype
输出
function myFunc() {}
myFunc.prototype = {
a: 1,
b: 2
};
printPrototypeChain(myFunc);
这些对象都没有定义[Function: myFunc]
[Function: Empty]
{}
,因此返回a
。但是,在这种情况下,
undefined
原型链变得像这样
function myFunc() {}
myFunc.__proto__ = {
a: 1,
b: 2
};
printPrototypeChain(myFunc);
和[Function: myFunc]
{ a: 1, b: 2 }
{}
位于a
的直接父母身上。因此,返回相应的值myFunc
。
注意:请勿在实际代码中使用1
,因为它是为了向后兼容而保留在最新版本的JavaScript规范中。阅读更多相关信息here。请改用Object.getPrototypeOf
和Object.setPrototypeOf
。
答案 1 :(得分:1)
您将myFunc
(一个构造函数)与myFunc
的实例混淆。
如果您这样做:
var o = new myFunc();
alert(o.a);
它会提醒1,因为o
是myFunc
的实例,因此其a
属性来自myFunc
原型。
如果您设置了__proto__
,那么您将真正地交换myFunc
之前继承的函数原型并将其替换为原型对象。事实上,在你这样做之后,你通常可以在函数上使用的任何方法,例如call
,都不会再在myFunc
找到。
myFunc.__proto__ = myObj;
myFunc.call(null); // Will throw an error
答案 2 :(得分:0)
所有JS对象都具有rst.MoveNext
系统属性。如果您尝试获取对象Do while not rst.EOF
CountCheck = CountCheck + 1
response.write("Count is: " & CountCheck & "<br>")
rst.MoveNext
Loop
的有效__proto__
值,则首先在对象x
属性中搜索此属性。如果找不到任何内容,将在a
个性能中搜索该属性。等等。
这就是您的示例中a
ruturns a.__proto__
的原因。
当您设置myFunc.a
时,这意味着在您创建1
的实例时将来会使用myFunc.prototype=myObj
:
myObj
这并不意味着myFunc
必须有var mf = new myFunc();
本身,正如我上面提到的那样。