为什么分配的东西给Something.prototype.constructor? [英] Why assign Something to Something.prototype.constructor?

查看:333
本文介绍了为什么分配的东西给Something.prototype.constructor?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在阅​​读关于JavaScript的原型属性如何与继承一起工作,然后开始通过Angular.js code的外观和一些问题出现了。

首先,我读了原型属性指向具有构造的属性,它指向回用于创建对象的原函数的对象。因此,例如:

//这是构造
功能形状(){
    this.position = 1;
}//构造点回到原来的功能,我们定义
Shape.protoype.constructor ==形状;

该原型还包含已经由我们或JavaScript语言本身上定义的任何其它方法或属性,而这些是由对象的所有实例共享。如果你想叫一个方形物体从形状继承你需要设置广场的原型等于形状的新实例,因为内部[[原型] Square.prototype的属性被设置为Shape.prototype财产公开对象值

函数广场(){}
Square.prototype =新形状();
VAR平方=新广场();
square.position; //这将输出1

这一切对我来说很有意义。

不过,Angular.js code,我有一个问题关于似乎与这一切,但做一些事情,我不明白。它似乎并不具有继承打交道,所以我可以理解为什么会有差异,但我只是好奇,为什么他们写,他们做的方式。

在Angular.js,有一个HashMap对象和一个词法对象,但它们有不同的定义尚未出现被实例化并在完全相同的方式使用。词法分析器构造函数首先定义,然后他们设置了原型对象应该由词法分析器的所有实例共享的常量,其中包含的方法。这一切都很有意义。我不明白的是为什么他们指定构造的属性,并设置它只是词法分析器,当他们下面的HashMap则没有。

VAR词法=功能(选件){
    this.options =选择;
};//注意它们指定词法分析器作为构造,即使他们下面的HashMap不
Lexer.prototype = {
    构造器:词法,
    法:功能(文本){...},
    是:功能(CH,字符){...},
    偷看:功能(ⅰ){...},
    ISNUMBER:功能(CH){...},
    isWhitespace:功能(CH){...},
    isIdent:功能(CH){...},
    isExpOperator:功能(CH){...},
    throwError:功能(错误,开始,结束){...},
    readNumber:功能(){...},
    readIdent:功能(){...},
    readString:函数(报价){...}
};

然后,如果你看的HashMap code,他们这样做只是它们不指定constructor属性同样的事情。为什么是这样?这似乎是完全一样的,我已经测试过的构造仍然被调用。

// HashMap的构造
功能的HashMap(数组,isolatedUid){
    如果(isolatedUid){
        VAR的uid = 0;
        this.nextUid =功能(){
            返回++ UID;
        };
    }
    的forEach(数组,this.put,这一点);
}HashMap.prototype = {
    放:功能(键,值){...},
    得到:功能(键){...},
    删除:功能(键){...}
};

原来是constructor属性选购时,有没有继承,所以也许一个人写的词法分析器和另一个HashMap中,一个决定指定的构造?


解决方案

默认情况下,每一个原型有一个构造属性,是指它属于功能

\r
\r

函数A(){\r
}\r
\r
的console.log(A.prototype.constructor === A); //真实

\r

\r
\r

如果您覆盖在其整体的原型对象文本或与其他一些构造原型,这个构造价值将得到擦干,并留下未定义或与其他一些值。

\r
\r

函数A(){\r
}\r
A.prototype = {\r
    问候:你好!\r
};\r
\r
的console.log(A.prototype.constructor === A); //假

\r

\r
\r

原型不需要为了构造属性构造正常运行,但人们经常会重新分配 prototype.constructor 回其初始值,以保持一致性,这就是你所看到的词法

考虑:

\r
\r

函数A(){\r
}\r
\r
函数B(){\r
}\r
\r
B.prototype =的Object.create(A.prototype);\r
\r
变种B =新的B();\r
\r
的console.log(b.constructor === A); //真\r
的console.log(b.constructor === B); //假\r
\r
B.prototype.constructor = B;\r
\r
的console.log(b.constructor === A); //假\r
的console.log(b.constructor === B); //真实

\r

\r
\r

人们只能猜测,为什么这被排除了的HashMap 。我怀疑这是任何好的理由做,可能只是一个监督。

I was reading about how the Javascript prototype property works along with inheritance and then began to look through the Angular.js code and came up with some questions.

First off, I read that the prototype property points to an object that has a "constructor" property which points back to the original function that is used to create the object. So for example:

// This is the constructor
function Shape() {
    this.position = 1;
}

// The constructor points back to the original function we defined
Shape.protoype.constructor == Shape;

The prototype also contains any other methods or properties that have been defined on it by us or by the Javascript language itself, and these are shared by all instances of the object. If you want an object called Square to inherit from Shape you need to set Square's prototype equal to a new instance of Shape because the internal [[prototype]] property of Square.prototype gets set to the public object value of the Shape.prototype property.

function Square() {}
Square.prototype = new Shape();
var square = new Square();
square.position; // This will output 1

This all makes sense to me.

However, the Angular.js code that I have a question about seems to be related to all of this but does something that I do not understand. It doesn't appear to be dealing with inheritance so I can understand why there would be differences, but I'm just curious why they wrote it the way they did.

Within Angular.js, there is a HashMap object and a Lexer object, but they are defined differently yet appear to be instantiated and used in the same exact way. The Lexer constructor is first defined, and then they set the prototype to an object literal containing methods that should be shared by all instances of the Lexer. This all makes sense. What I don't understand is why they specify the "constructor" property and set it to just "Lexer" when they don't for HashMap below.

var Lexer = function(options) {
    this.options = options;
};

// Notice they specify Lexer as the constructor even though they don't for HashMap below
Lexer.prototype = {
    constructor: Lexer,
    lex: function(text) { ... },
    is: function(ch, chars) { ... },
    peek: function(i) { ... },
    isNumber: function(ch) { ... },
    isWhitespace: function(ch) { ... },
    isIdent: function(ch) { ... },
    isExpOperator: function(ch) { ... },
    throwError: function(error, start, end) { ... },
    readNumber: function() { ... },
    readIdent: function() { ... },
    readString: function(quote) { ... }
};

Then if you look at the HashMap code, they do the same thing except that they do not specify the constructor property. Why is this? It appears to work exactly the same, and I've tested that the constructor still gets called.

// The HashMap Constructor
function HashMap(array, isolatedUid) {
    if (isolatedUid) {
        var uid = 0;
        this.nextUid = function() {
            return ++uid;
        };
    }
    forEach(array, this.put, this);
}

HashMap.prototype = {
    put: function(key, value) { ... },
    get: function(key) { ... },
    remove: function(key) { ... }
};

So is the constructor property optional when there is no inheritance, so maybe one person wrote the Lexer and another the HashMap and one decided to specify the constructor?

解决方案

By default, every prototype has a constructor property that refers to the function that it "belongs" to.

function A() {
}

console.log(A.prototype.constructor === A); // true

If you overwrite a prototype in its entirety with an object literal or with some other constructed prototype, this constructor value will get wiped away and be left undefined or with some other value.

function A() {
}
A.prototype = {
    greeting: "Hello!"
};

console.log(A.prototype.constructor === A); // false

The prototype constructor property is not needed in order for the constructor to operate correctly, but people will often reassign prototype.constructor back to its initial value in order to maintain consistency, and that's what you are seeing for Lexer.

Consider:

function A() {
}

function B() {
}

B.prototype = Object.create(A.prototype);

var b = new B();

console.log(b.constructor === A); // true
console.log(b.constructor === B); // false

B.prototype.constructor = B;

console.log(b.constructor === A); // false
console.log(b.constructor === B); // true

One can only speculate as to why this was left out for HashMap. I doubt it was done for any good reason and may have just been an oversight.

这篇关于为什么分配的东西给Something.prototype.constructor?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆