[英]Why do classes and functions behave differently in Javascript?
我的理解是所有類本質上都是函數,所有實例都是對象。 但有些事讓我很困惑。
//Take this for example: function AnimalFunc(name) { this.name = name; this.sayName = function() { console.log(this.name); } } //And compare it with this: class AnimalClass { constructor(name) { this.name = name; } sayName() { console.log(this.name); } } //Now I instantiate them. cat = new AnimalFunc("cat") cat.sayName() // -> "cat" dog = new AnimalClass("dog") dog.sayName() // -> "dog" console.log(Object.keys(cat)); console.log(Object.keys(dog));
預期觀察:
typeof(AnimalClass)
和typeof(AnimalFunc)
都返回function
。 typeof(cat)
和typeof(dog)
都返回object
。 意外觀察:
Object.keys(cat)
,我會得到["name","sayname"]
。 Object.keys(dog)
,我得到["name"]
。 我的問題是:為什么我沒有將sayname
作為類實例的鍵? 為什么我只為函數實例獲取它?
第一個示例帶有一個函數,在創建實例時會創建一個新的函數屬性,因此會為Object.keys
提取一個新的鍵。
第二個示例使用類將函數屬性分配給對象的prototype
。 因此,實際上並沒有創建新密鑰,並且可以通過走向原型鏈找到sayName
函數。
您可以通過執行以下操作來復制類行為:
function AnimalFunc(name) {
this.name = name
}
AnimalFunc.prototype.sayName = function () {
console.log(this.name)
}
如果您想熟悉JS的原型模型,可以閱讀以下內容。 如果你願意,可以通過搜索“javascript原型”找到更多的文章等。
因為您已聲明了兩個名為name
和sayname
屬性
this.name;
this.sayname;
在類AnimalClass
您只將屬性聲明為構造函數體中的鍵name
:
this.name = ....
Object.keys()返回一個數組,其元素是與直接在對象上找到的可枚舉屬性相對應的字符串。 屬性的順序與手動循環對象的屬性所給出的順序相同。
所以,基本上會直接返回屬性使用上下文聲明this
。
class AnimalClass { constructor(name) { this.name = name; // This is just to illustrate! this.sayName = function() { console.log(this.name); } } } console.log(Object.keys(new AnimalClass('Dog')))
這是因為AnimalClass的sayName
在AnimalClass的原型中,而AnimalFunc的sayName
不是,它是實例的一部分( this
)。
在AnimalClass的情況下,只有一個sayName
函數,所有實例共享對以下內容的引用:
class AnimalClass { constructor(name) { this.name = name; } sayName() { console.log(this.name); } } var a = new AnimalClass("a"), b = new AnimalClass("b"); a.sayName === b.sayName; // true
每個AnimalFunc實例都有自己的sayName
定義,因為它在構造函數中為每個實例重新定義:
function AnimalFunc(name) { this.name = name; this.sayname = function() { console.log(this.name); } } var a = new AnimalFunc("a"), b = new AnimalFunc("b"); a.sayName === b.sayName; // false
使用function
的AnimalClass的等價是:
function AnimalFunc(name) {
this.name = name;
}
AnimalFunc.prototype.sayname = function() {
console.log(this.name);
}
而使用class
的AnimalFunc相當於:
class AnimalClass {
constructor(name) {
this.name = name;
this.sayName = function() {
console.log(this.name);
}
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.