2014-12-02 26 views
1

我想學習如何使用Object.defineProperties()。我使用下面的代碼:JavaScript:使用Object.defineProperties()

var Person = function(firstName, lastName) 
{ 
    this.firstName = firstName; 
    this.lastName = lastName; 
}; 

Object.defineProperties(Person, { 
    sayHi : { 
     get : function() {return "Hello";}, 
     enumerable : true 
    }, 
    sayBye : { 
     get : function() {return "Bye";}, 
     enumerable : true 
    } 
}); 


var john = new Person('John', 'Doe'); 
console.log(john.sayHi()); 

但我不斷收到:

TypeError: john.sayHi is not a function 
console.log(john.sayHi()); 

有人能告訴我什麼是錯的代碼?

謝謝

+1

你可能想在'Person.prototype'上定義屬性,而不是在'Person'構造函數上。這對於如何使用Object.defineProperties並不是問題,但是您可能會對理解原型繼承在JavaScript中的工作原理有問題。 (注意''sayBye'之前缺少逗號,但我認爲這只是一個錯字。) – apsillers 2014-12-02 14:58:23

+0

它應該仍然有效。我正在學習一個教程,當導師運行它時,完全相同的代碼正在工作。 – 2014-12-02 15:00:29

+1

你能分享一個指南的鏈接嗎?除了不正確的原型設置之外,還要注意'sayHi'和'sayBye'具有返回* strings *的getter,而不是函數。即使你正確的做了Object.defineProperties(Person.prototype,...),那麼john.sayHi也不會是一個函數。它將是字符串「'Hello'」。 – apsillers 2014-12-02 15:03:48

回答

3

那麼,你沒有定義sayHi作爲一個函數。這是怎麼它定義爲一個函數:

var Person = function(firstName, lastName) 
{ 
    this.firstName = firstName; 
    this.lastName = lastName; 
}; 
// Define the properties on the prototype, not the Person object itself 
Object.defineProperties(Person.prototype, { 
    sayHi : { 
     get : function() { 
      return function() { 
      return "Hello, I am " + this.firstName + " " + this.lastName; 
      }; 
     }, 
     enumerable : true 
    }, 
    sayBye : { 
     get : function() { 
      return function() { 
      return "Bye"; 
      }; 
     }, 
     enumerable : true 
    } 
}); 

var john = new Person('John', 'Doe'); 
console.log(john.sayHi()); 
console.log(john.sayBye()); 

準確地說:在你的代碼,john.sayHi返回「你好」的字符串,它是一個字符串原始的,因此絕對不是一個功能;-)

該屬性的get函數必須返回一個函數才能實現所需。

爲了給你一個較長的回答,請參閱本以下其他實施,同時充分的兩點優勢:從ES5(Object.create())和ES6(Object.defineProperties())和JS的原型性質(沒有用new運營商的第一個新功能,原型繼承):

var Person = { 
    init: function(firstName, lastName) { 
     this.firstName = firstName; 
     this.lastName = lastName; 
    } 
}; 

Object.defineProperties(Person, { 
    sayHi : { 
     get : function() {return function() {return "Hello, I am " + this.firstName + " " + this.lastName;}}, 
     enumerable : true 
    }, 
    sayBye : { 
     get : function() {return function() {return "Bye";};}, 
     enumerable : true 
    } 
}); 

var Employee = Object.create(Person); // Employee inherits from Person 

Employee.init = function(firstName, lastName, position) { 
    this.firstName = firstName; 
    this.lastName = lastName; 
    this.position = position; 
}; 

Object.defineProperties(Employee, { 
    introduce : { 
     get : function() {return function() { 
      return this.sayHi() + ", " + this.position; 
     }}, 
     enumerable : true 
    }, 
    farewell : { 
     get: function() {return function() { 
      return this.sayBye() + ", it was a pleasure to meet you"; 
     }}, 
     enumerable: true 
    } 
}); 

var john = Object.create(Employee); // john inherits from Employee 
john.init('John', 'Doe', 'Manager'); 

console.log(john.sayHi()); // Inherited from Person 
console.log(john.introduce()); // Inherited from Employee 
console.log(john.sayBye()); // Inherited from Person 
console.log(john.farewell()); // Inherited from Employee 

JSFIddle demo

+1

可能值得一提的是你將它應用於Person.prototype而不僅僅是Person,所以你可以把它叫做john.sayHi()而不是Person.sayHi() ' – Rhumborl 2014-12-02 15:10:21

+0

@Rhumborl是的,你說得對,它已經完成了;-) – laruiss 2014-12-02 15:18:00

+0

@laruiss:因爲你在原型上定義它,所以它就像一種魅力。任何想法,爲什麼它不會工作,如果我在Person上定義屬性?正如我所提到的,在我正在學習的教程中,作者在Person上定義了這個屬性,並且它似乎對他有效。 – 2014-12-02 15:29:57

1

更換

get : function() {return "Hello";} with 

get : function() {return function() {return "Hello";};}