2010-08-30 24 views
20

Greetings,Làm cách nào để gọi một trình tạo mã JavaScript được kế thừa với các tham số?

Sau khi đọc bài viết sau đây tôi có một câu hỏi: https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript

Trong ví dụ thừa kế, các nhà xây dựng Person không mất bất kỳ thông số. Ví dụ này sẽ trông như thế nào nếu tôi thêm một cái và gọi nó từ hàm tạo Sinh viên?

Cảm ơn!

Trả lời

38

Vâng, một cách mà bạn có thể tái sử dụng logic của các nhà xây dựng Person là cách gọi nó với call hoặc apply, ví dụ:

function Person(gender) { 
    this.gender = gender; 
} 

function Student(gender) { 
    Person.apply(this, arguments); 
} 
Student.prototype = new Person(); // make Student inherit from a Person object 
Student.prototype.constructor = Student; // fix constructor property 

var foo = new Student('male'); 
foo.gender;    // "male" 
foo instanceof Student; // true 
foo instanceof Person; // true 

Nếu bạn muốn ngăn chặn việc thực hiện các constructor Person khi được gọi là không có đối số (như trong dòng: Student.prototype = new Person();), bạn có thể phát hiện nó, ví dụ:

function Person(gender) { 
    if (arguments.length == 0) return; // don't do anything 
    this.gender = gender; 
} 
+1

@CMS Đối với phần thứ hai 'if (arguments.length == 0) trả về;', có cách nào để xử lý các hàm tạo trong đó các đối số KHÔNG được yêu cầu không? Trong tình huống đó, tôi có bị buộc phải gọi cho nhà xây dựng không? –

+0

Tôi đã thử nhiều phương pháp khác nhau ('Object.create',' Person.prototype', các chức năng tạm thời ...) nhưng tất cả chúng đều thất bại hoặc có lỗi (các thuộc tính không xác định, các thuộc tính bị che khuất, v.v.). Cảm ơn câu trả lời này, cuối cùng câu trả lời đó thực sự hiệu quả! – TheBronx

0
// define the Person Class 
function Person(name) { 
    this.personname = name; 
} 

Person.prototype.walk = function(){}; 
Person.prototype.sayHello = function(){ 
    alert (this.personname); 
}; 

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor


Mã đầy đủ:

<script> 
// define the Person Class 
function Person(name) { 
    this.personname = name; 
} 

Person.prototype.walk = function(){}; 
Person.prototype.sayHello = function(){ 
    alert (this.personname); 
}; 

// define the Student class 
function Student() {} 

// inherit Person 
Student.prototype = new Person("test"); 

// correct the constructor pointer because it points to Person 
Student.prototype.constructor = Student; 

// replace the sayHello method 
Student.prototype.sayHello = function(){ 
    alert('hi, I am a student and my name is \'' + this.personname + '\''); 
} 

// add sayGoodBye method 
Student.prototype.sayGoodBye = function(){ 
    alert('goodBye'); 
} 

var student1 = new Student(); 
student1.sayHello(); 
student1.sayGoodBye(); 
</script> 
+1

Tôi nghĩ làm việc này tốt nếu bạn luôn muốn "test" như tên người, nhưng đây không phải là những gì tôi có nghĩa là khi tôi yêu cầu để gọi nó từ Sinh viên xây dựng. – kgarske

9

Được chấp nhận câu trả lời có vẻ là không chính xác . Dựa trên những gì Mozilla says about OO JavaScript, cách chính xác để làm điều đó là:

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

function Student(firstName, subject) { 
    // Call the parent constructor, making sure (using Function#call) 
    // that "this" is set correctly during the call 
    Person.call(this, firstName); 

    // Initialize our Student-specific properties 
    this.subject = subject; 
}; 

// Create a Student.prototype object that inherits from Person.prototype. 
// Note: A common error here is to use "new Person()" to create the 
// Student.prototype. That's incorrect for several reasons, not least 
// that we don't have anything to give Person for the "firstName" 
// argument. The correct place to call Person is above, where we call 
// it from Student. 
Student.prototype = Object.create(Person.prototype); // See note below 

// Set the "constructor" property to refer to Student 
Student.prototype.constructor = Student; 

// Example usage: 
var student1 = new Student("Janet", "Applied Physics"); 

Như bạn có thể thấy rõ, Mozilla xác định rằng đó là một lỗi phổ biến để sử dụng "Người mới()" để tạo ra các Student.prototype. Do đó chấp nhận câu trả lời là gây hiểu lầm.

Tôi đã thực sự thử nghiệm điều này trong dự án đang diễn ra của mình và cách của Mozilla là chính xác, trong khi câu trả lời ở trên không hoạt động.

0

Bằng tất cả các nhận xét khác, tôi đã tạo một ví dụ phù hợp với tôi. Vì tôi không sử dụng nguyên mẫu một cách rõ ràng nên tôi hy vọng tôi không bỏ lỡ một điểm quan trọng nào.

// variable for tracking instantiations and checking the uniqueness of the objects 
var instances = 0; 

var Generic = function() { 
    this.instanceId = ++instances; 
    this.toString = function() {return 'Generic [iid='+ this.instanceId +']'}; 
    console.log('constructor-invoke: Generic ('+ this.instanceId +')'); 
}; 

var SpecificName = function(inName) { 
    Generic.call(this); 
    this.getName = function() { return inName; };  
    var superToString = this.toString.bind(this); // binds the inner function 'this' to this SpecificName instance 
    this.toString = function() { 
     return 'SpecificName [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']' 
    } 
    console.log('constructor-invoke: SpecificName ('+ this.instanceId +')'); 
}; 

var SpecificNames = function(inFirstName, inLastName) { 
    SpecificName.call(this, inLastName +', '+ inFirstName); 
    var superToString = this.toString.bind(this); 
    this.toString = function() { 
     return 'SpecificNames [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']' 
    } 
    console.log('constructor-invoke: SpecificNames ('+ this.instanceId +')'); 
}; 

var g = new Generic(); 
var sn = new SpecificName('Run Forest Run'); 
var sns = new SpecificNames('Forest','Gump'); 

console.log('g: '+ g.toString()); 
console.log('sn: '+ sn.toString()); 
console.log('sns: '+ sns.toString()); 

dẫn đến kết quả này:

constructor-invoke: Generic (1) 
constructor-invoke: Generic (2) 
constructor-invoke: SpecificName (2) 
constructor-invoke: Generic (3) 
constructor-invoke: SpecificName (3) 
constructor-invoke: SpecificNames (3) 
g: Generic [iid=1] 
sn: SpecificName [iid=2, name=Run Forest Run, super.toString=Generic [iid=2]] 
sns: SpecificNames [iid=3, name=Gump, Forest, super.toString=SpecificName [iid=3, name=Gump, Forest, super.toString=Generic [iid=3]]] 
Các vấn đề liên quan