2017-11-25 99 views
1

我很奇怪,爲什麼在這段代碼,當我試圖訪問該garfield製成的,在這種情況下Cat對象的屬性,我得到undefinedJS - 原型繼承與對象創建功能

function Cat(){ 
    this.legs = 2; 
    this.species = 'cat'; 
}; 

Cat.prototype.makeSound = function() { 
    console.log(this.sound); // logs undefined 
}; 

const garfield = Object.create(Cat); 
garfield.sound = 'feed me'; 
garfield.makeSound(); 
console.log(garfield.legs) // logs undefined 

我不應該能夠讓原型繼承鏈訪問這些屬性嗎?

回答

3

單詞OOP在其定義中包含「對象」;這意味着你正在處理對象。

Javascript做了一些特殊的事情,它直接暴露對象,你可以在沒有抽象的情況下使用它們(沒有類)。

要創建一個對象,您可以用{}聲明它。例如,不需要創建一個類來獲得類似於java的類。

要直接使用繼承,您需要有一個對象,並將其附加到其原型。

下面是一個例子:

const Cat = { 
 
    legs: 2, 
 
    species: 'cat', 
 
}; 
 

 
Object.setPrototypeOf(Cat, { 
 
    makeSound() { 
 
    console.log(this.sound); // logs undefined 
 
    } 
 
}) 
 

 

 
const garfield = Object.create(Cat); 
 
garfield.sound = 'feed me'; 
 
garfield.makeSound(); 
 
console.log(garfield.legs) //2

使用繼承使用功能,你必須先建立函數來獲取對象了功能(this)和原型將自動附加到this對象。

function Cat(){ 
 
    this.legs = 2; 
 
    this.species = 'cat'; 
 
}; 
 

 
Cat.prototype.makeSound = function() { 
 
    console.log(this.sound); // logs undefined 
 
}; 
 

 
const garfield = new Cat(); 
 
garfield.sound = 'feed me'; 
 
garfield.makeSound(); 
 
console.log(garfield.legs) // 2

+0

我沒有看到一個理由使用'Object.setPrototypeOf'這裏,只要把' 'Cat'對象上的makeSound'。 – Bergi

2

在您的例子Object.create創建該類的新實例!它創建一個函數(因爲Cat是一個函數,你傳遞函數的原型)!

使用new創建一個新的實例

const garfield = new Cat(); 
console.log(garfield.legs); 

function GarfieldLikeCat() {} 
GarfieldLikeCat.prototype = Object.create(Cat.prototype); 
GarfieldLikeCat.prototype.constructor = GarfieldLikeCat; 

獲得古典繼承(不是一個新的實例!)。

如果你沒有使用this.legs = 2;,而是Cat.prototype.legs = 2;,你可以使用Object.create創建一個新的實例

function Cat() {} 
Cat.prototype.legs = 2; 
const garfield = Object.create(Cat.prototype); 
console.log(garfield.legs); 
+0

+1。但是請注意,如果不調用構造函數,就不會構造對象(即在本例中'leg'和'species'不會被添加到garfield中),所以它更好的方法是使用'new',直接使用對象,或創建工廠功能。 – Bamieh