javascript如何通过其原型链查找对象的成员?

时间:2012-03-24 07:03:22

标签: javascript

评估时的价值 myObject.myMember

我的猜测是,javascript会尝试查找“myMember”条目:


    myObject
    myObject.constructor.prototype
    myObject.constructor.prototype.constructor.prototype
    myObject.constructor.prototype.constructor.prototype.constructor.prototype
    .......

直到成功。

以下代码似乎验证了我的猜测

var MyClass1=function(){
    this.key1="value1"; 
};
var myObject=new MyClass1();

MyClass1.prototype.key2="value2";

console.log(myObject.constructor.prototype.key2=="value2"); //true
console.log(myObject.key2=="value2"); //true   :)

但以下代码证明我猜错了

var MyClass1=function(){
    this.key1="value1"; 
};

var MyClass2=function(){
    this.key2="value2"; 
};

var myObject=new MyClass1();

MyClass1.prototype=new MyClass2();
console.log(myObject.constructor.prototype.key2=="value2");//true
console.log(myObject.key2=="value2");// false! why?

javascript通过其原型链查找对象成员的实际算法是什么?

2 个答案:

答案 0 :(得分:0)

这是因为在创建myObject实例后,您“重新定义”MyClass1。 这就是它的工作原理:

function BaseClass() {
   this.key1 = "value";
};

BaseClass.prototype.method1 = function()  { };

function SubClass() {
    this.key2 = "value";
}

SubClass.prototype = new BaseClass();
SubClass.prototype.constructor = SubClass;  //just to have classnames rendered correctly in webkit
SubClass.prototype.method2 = function()  { };

var instance = new SubClass();

console.log(instance instanceof BaseClass); //true
console.log(instance instanceof SubClass); //true
console.log("key1" in instance); //true
console.log(instance.hasOwnProperty(key1));// false
console.log(instance.hasOwnProperty(key2));// true
console.log("key2" in instance); //true;
console.log("method1" in instance); //true;
console.log("method2" in instance); //true;

同样遵循prototypechain最好使用Object.getPrototypeOf(Object.getPrototypeOf(...))

答案 1 :(得分:0)

这是因为您在创建MyClass1.prototype=new MyClass2();的实例后调用了MyClass1

var MyClass1=function(){
    this.key1="value1"; 
};

var MyClass2=function(){
    this.key2="value2"; 
};

MyClass1.prototype=new MyClass2();

var myObject=new MyClass1();

myObject.key1 === "value1";
myObject.key2 === "value2";

让我们检查操作var myObject=new MyClass1()

new运算符(http://es5.github.com/#x11.2.2)调用[[Construct]]的{​​{1}}内部方法(当然是伪代码)。

这是myClass1http://es5.github.com/#x13.2.2)次调用(显然是伪代码)中发生的内容的略读版本:

[[Construct]]

通过“实际原型”,我的意思不是你看到的//fun in our operation is MyClass1 function Construct ( fun ) { //we create a fresh new object var obi = makeNewObject(); //grab the prototype of MyClass1 var proto = fun.prototype; //and set the actual prototype of obi to that prototype setPrototype( obi, proto ); //and then returning the created and altered object, that will be myObject return obi; } - 原型向前看,我们将要创建的实例。对象的fun.prototype是继承它的属性,它是它的过去。

可以使用[[Prototype]]检索,并且在某些实现中可以使用非标准Object.getPrototypeOf进行设置。

好的,现在我们已经确定了如何使用obj.__proto__创建对象,为什么你的示例不起作用?

创建new后替换MyClass1.prototype会破坏两者之间的链接。 myObject已经移到了黑暗的一面,它已经完全改变了,一个新的对象现在取代了它,MyClass1与此无关。

在更改myObject之前,它包含对象myObject.__proto__ === MyClass1.prototype的引用。更改对象MyClass1.prototype后,MyClass1.prototype将继续引用该旧对象而不是新对象。

答案已经完成了。要重新发布 - myObject.__proto__功能会在[[Construct]]MyClass1.prototype之间建立链接。当您替换myObject时,该链接不会更改,因此MyClass1.prototype会很乐意使用最初链接到的对象。

如果你仍然对如何完成属性提取感到好奇:http://es5.github.com/#x8.12.2我警告你,spec语言读起来很乏味。