对象的javascript原型

时间:2014-10-10 10:28:59

标签: javascript object prototype

原型如何运作?为什么" xc"无法从e对象访问?

请向下看代码,看评论,我在chorme中测试

var x={a:"xa",b:"xb",c:"xc"};
var e={a:"ea",b:"eb"};
console.log(Object.prototype); // this is {} why? i am expecting it to be null
console.log(e.prototype);
e.prototype=x;
console.log(e.prototype);
console.log(x.c);
console.log(e.c);//this is undefined , why?  i am expecting it to be "xc"
console.log(e.a);
console.log(e.b);
console.log(e.prototype.a);
console.log(e.prototype.b);

我首先认为它在css合并中很有用,后来我认为要解决依赖关系,然后重写css更合理,但知识是真实的。非常感谢。

var css={

    'classSelectorExpressionIDOnly1':{
        css_Ruls_name1:xxxx,
        css_Rulss_name2:xxxx

    }

    'classSelectorExpressionIDOnlyX':{
        css_Ruls_name1:xxxx,
        css_Rulss_name9:xxxx

    }

    'classSelectorExpressionIDOnly2':{ '()inherit':["classSelectorExpressionIDOnly1","classSelectorExpressionIDOnlyX"]
        css_Ruls_name3:xxxx,
        css_Rulss_name5:xxxx

    }


}


var mergeResult = Object.create(css.classSelectorExpressionIDOnly2);
for(var entry in mergeResult){
    mergeResult[entry]= mergeResult[entry];
}
mergeResult.__proto__=css.classSelectorExpressionIDOnly1;
for(var entry in mergeResult){
    mergeResult[entry]= mergeResult[entry];
}
mergeResult.__proto__=css.classSelectorExpressionIDOnlyX;
for(var entry in mergeResult){
    mergeResult[entry]= mergeResult[entry];
}

------依赖重写--------

.classSelectorExpressionIDOnly1,.classSelectorExpressionIDOnly2{
        css_Ruls_name1:xxxx,
        css_Rulss_name2:xxxx
}
.classSelectorExpressionIDOnlyX,.classSelectorExpressionIDOnly2{
        css_Ruls_name1:xxxx,
        css_Rulss_name9:xxxx
}
.classSelectorExpressionIDOnly2{
        css_Ruls_name3:xxxx,
        css_Rulss_name5:xxxx
}

2 个答案:

答案 0 :(得分:1)

看看这里: https://stackoverflow.com/a/9959753/2768053

阅读完之后,您将把代码转换为:

var x={a:"xa",b:"xb",c:"xc"};
var e={a:"ea",b:"eb"};
console.log(Object.prototype.__proto__); 
console.log(e.__proto__);
e.__proto__=x;
console.log(e.__proto__);
console.log(x.c);
console.log(e.c);
console.log(e.a);
console.log(e.b);
console.log(e.__proto__.a);
console.log(e.__proto__.b);

您将得到您期望的结果:)

答案 1 :(得分:1)

这不是.prototype属性的用途。尽管有名称,但函数的.prototype属性实际上并不是原型的您习惯使用的对象。 这是关于JavaScript 最难理解的事情之一,所以它不仅仅是你。

在JavaScript中理解原型系统的关键是 new运算符创建两个对象,而不是一个。我将用四个变量来讨论这个问题:

[[myPrototype]]
对象的原型。理论上每个对象都有一个(虽然对于某些对象,它可能是未定义的)。
[[构造]]
使用New运算符
调用的函数
[[NEWOBJECT]]
最终将返回的对象
[[newPrototype]]
将成为[[newObject]]。[[myPrototype]]
的对象

请注意,这些JavaScript名称不是有效的(实际上,它们在大多数编程语言中都不是有效名称)。所有这些都发生在幕后,大多数实现也没有使用这些名称。我这样做是为了表明你无法正常看到这些物品。

当您使用new运算符时,JavaScript大致执行以下步骤。

  1. 创建一个对象[[newPrototype]]。
  2. 将[[newPrototype]]。[[myPrototype]]设置为[[Constructor]]。原型
  3. 创建一个对象[[newObject]]。
  4. 将[[newObject]]。[[myPrototype]]设置为[[newPrototype]]
  5. 将[[newObject]]。[[myPrototype]]。构造函数设置为[[Constructor]]
  6. 调用[[Constructor]],[[newObject]]为"此"。
  7. 注意[[newObject]]。[[myPrototype]]并不是[[newObject]]或[[Constructor]]。prototype的完美匹配。这就是为什么我们需要它们之间的第三个对象:它携带你想要继承的信息(通过[[newPrototype]]。[[myPrototype]]),但它也包含特定于你所对象的对象的信息。重新创建(在[[newObject]]。constructor)。

    所以我们得到.prototype函数的用途。它不是函数的[[myPrototype]],而且它不是您使用new创建的对象的[[myPrototype]]。它实际上是原型链中的两个级别,而不是一个级别。

    我希望这个解释可以帮助您了解.prototype函数的用途。这不是简单的事情,并不是每个人都会点击每个解释。这就是为什么我们在这里有这么多解释的部分原因。

    首次创建对象时,可以使用Object.create() 直接设置原型。此功能适用于IE9及更高版本(以及所有其他现代浏览器),如果您需要使用旧版浏览器,则可以将其填充。 稍后要查看该原型,您可以使用Object.getPrototypeOf() ,它也具有良好的浏览器支持(尽管IE仅在版本9及更高版本中支持它)。仅使用这两个函数,您可以创建如下对象:

    var x = {a:"xa",b:"xb",c:"xc"};
    var e = Object.create(x);
    x.a = "ea";
    x.b = "eb";
    console.log(Object.getPrototypeOf(Object));
    console.log(Object.getPrototypeOf(e));
    console.log(x.c);
    console.log(e.c);//this is undefined , why?  i am expecting it to be "xc"
    console.log(e.a);
    console.log(e.b);
    console.log(Object.getPrototypeOf(e).a);
    console.log(Object.getPrototypeOf(e).b);    
    

    创建对象后,还没有一种标准方法可以重置原型 。 ECMAScript 6定义了一个(Object.setPrototypeOf()函数),但到目前为止只有Chrome和Firefox支持它:IE和Safari不支持。不过,如果可以的话,你可以这样做:

    var x = {a:"xa",b:"xb",c:"xc"};
    var e = {a:"ea",b:"eb"};
    console.log(Object.getPrototypeOf(object));
    console.log(Object.getPrototypeOf(e));
    Object.setPrototypeOf(e, x);
    console.log(Object.getPrototypeOf(e));
    console.log(x.c);
    console.log(e.c);
    console.log(e.a);
    console.log(e.b);
    console.log(Object.getPrototypeOf(e).a);
    console.log(Object.getPrototypeOf(e).b);
    

    重置现有对象原型的非标准方法,现在它甚至享有良好的浏览器支持。为此,您可以在任何标准对象上设置.__proto__属性。您可以像这样使用它:

    var x = {a:"xa",b:"xb",c:"xc"};
    var e = {a:"ea",b:"eb"};
    console.log(object.__proto__);
    console.log(e.__proto__);
    e.__proto__ = x;
    console.log(e.__proto__);
    console.log(x.c);
    console.log(e.c);
    console.log(e.a);
    console.log(e.b);
    console.log(e.__proto__.a);
    console.log(e.__proto__.b);
    

    现在,关于你的最后一个问题:为什么Object.prototype等于{},而不是未定义?因为Object构造函数具有.prototype属性,该属性成为通过它创建的所有对象的默认原型。规范称这个对象为[[ObjectPrototype]],它就像.hasOwnProperty()函数之类的东西一样。