2010-02-05 21 views

Trả lời

2

JavaScript không sử dụng các lớp giống như Java, C++ hoặc tương tự.

Một cách để đạt được hiệu quả của bạn là xác định hàm trong đó từ khóa này được sử dụng - truy cập vào các thành viên gần như bạn làm trong Java. Sau đó, sử dụng từ khóa mới để gọi hàm này để tạo đối tượng.

function Foo(){ //vaguely like a Java constructor 
    this.aField = 1; //define members simply by using 'this' 
    this.aMethod = methodFunction; //assign a function as a member using 'this' 
} 

function methodFunction(){ 
} 

var foo = new Foo(); //construct an object 
+0

đã ấn định phương thức gán; hy vọng bạn không nhớ ... – Christoph

+1

Trừ khi bạn đang sử dụng 'methodFunction' trong nhiều hơn một lớp, định nghĩa nó bên ngoài' f' không có mục đích thực sự trừ việc gây ô nhiễm phạm vi toàn cục. –

+0

@Justin: định nghĩa 'methodFunction()' bên ngoài hàm tạo nhất chắc chắn phục vụ một mục đích thực: nếu không, một đối tượng hàm mới phải được tạo cho mỗi cá thể (tức là một giá trị 'O (N)' trong số 'f' các đối tượng); thông thường, tôi sẽ gán phương thức cho 'f.prototype', nhưng làm như vậy sẽ làm chậm tìm kiếm phương thức – Christoph

4

Cách tiếp cận đối tượng định hướng bản địa nhất để Javascript là sử dụng thừa kế nguyên chủng, nhưng nhiều người mẫu khác tồn tại, bao gồm cả thừa kế pseudoclassical, mà bắt chước mô hình thừa kế dựa trên lớp bằng các ngôn ngữ như C và Java. Douglas Crockford đã viết và nói về chủ đề này và cung cấp một số giải thích rất tốt về mỗi chủ đề. Hãy xem những bài viết này:

Prototypal Inheritance in JavaScript

Classical Inheritance in JavaScript

10
// I like this pattern.. 

// class 
function Person(name, birthdate) { 
    this._name = name; 
    this._birthdate = birthdate; 
    /* should not do this 
    * this.getAge = function() { 
    * } 
    * as the method will be constructed 
    * for each instance, better to let it 
    * be inherited from prototype, see below 
    */ 
} 

// class methods 
Person.prototype.getBirthdate = function() { 
    return this._birthdate; 
} 

// same as above, function as a method 
Person.prototype.getAge = function() { 
    var currentDate = new Date(); 
    // age in millis 
    return currentDate - this._birthdate; 
} 

// the get age method can be a "static" 
// method on the constructor function if you pass the 
// person object 
Person.getAge = function(person) { 
    var currentDate = new Date(); 
    // age in millis 
    //no reference to this 
    return currentDate - person.getBirthdate(); 
} 

// you could use it like this 

myPerson = new Person("Steve", new Date("1980-01-01")); 
// returns age in millis 
myPerson.getAge(); 
// returns age in millis 
Person.getAge(myPerson); 

Bạn cũng có thể sử dụng một chức năng ẩn danh để mô phỏng tư nhân và công cộng

var PersonFactory = (function() { 
    // private area, no one can alter 
    // the person cache 
    var _cache = {} 

    // public area 
    return { 
    // returns a person born now 
    getPerson: function(name) { 
     if(_cache[name]) { 
     return _cache[name]; 
     } 
     else { 
     _cache[name] = new Person(name, new Date()); 
     return _cache[name]; 
     } 
    } 
    } 
})(); 

var p = PersonFactory.getPerson("Leif"); 
p.getAge(); 
p = PersonFactory.getPerson("Leif"); 
// should be the same age/obj 
p.getAge(); 

tôi không thích mô hình này Tuy nhiên. Cảnh báo gạch dưới _myVariable phải đủ để ngăn người dùng lib của bạn sử dụng các biến/phương thức đó. Tôi sử dụng nó allot khi tôi lần đầu tiên phát hiện ra nó vì nền Java của tôi .. Nó làm cho nó khó khăn để làm việc với thừa kế nguyên mẫu và có thể gây rò rỉ bộ nhớ.

+0

sử dụng bộ nhớ cache khi bạn mô tả nó cũng đánh bại bộ sưu tập rác tự động vì người lập trình hiện phải đảm bảo xóa các tài nguyên không cần thiết theo cách thủ công – Christoph

+0

Cảm ơn, đã chỉnh sửa. – oyvindn

22

Trong JavaScript "hiện đại", có ba phương pháp phổ biến để xác định đối tượng.

Phương pháp đầu tiên là phương pháp cổ điển và vẫn phổ biến vì tính đơn giản của nó; tuy nhiên, nó là discouraged by MDC có lợi cho phương pháp thứ hai vì sự thiếu hiệu quả của việc phải xác định lại từng chức năng mỗi khi một cá thể của đối tượng được tạo ra.

// Constructor, methods and members all rolled up into one definition 
var Movie = function(name) { 
    this.name = name; 
    // Note that private members can be created using the closure property 
    var _id = +(new Date()); 

    this.getName = function() { 
     return this.name + " " + _id; 
    }; 

    this.setName = function(name) { 
     this.name = name; 
    }; 
}; 

var m = new Movie("Beerfest"); 

Phương pháp thứ hai là một biến thể và có thể được sử dụng thay thế lẫn nhau lần đầu tiên. Nó cũng hữu ích cho việc thêm các phương thức mới vào các đối tượng hiện có thông qua thuộc tính prototype. Các thành viên và phương pháp riêng không thể thực hiện được dưới dạng này.

// Constructor is separate from its methods 
var Movie = function(name) { 
    this.name = name; 
} 

Movie.prototype.getName = function() { 
    return name; 
}; 

Movie.prototype.setName = function(name) { 
    this.name = name; 
}; 

var m = new Movie("Kill Bill"); 

Phương pháp thứ ba là sử dụng module pattern, mà làm cho nó có thể nhanh chóng đối tượng mà không cần phải sử dụng toán tử new.

var Movie = function (name) { 
    var _id = +(new Date()); 
    var privateMethod = function() { alert(_id); }; 

    // All methods and members defined here are public 
    return { 
     name: name, 
     getName: function() { 
      return this.name + " " + _id; 
     }, 
     setName: function(name) { 
      this.name = name; 
     } 
    }; 
}; 

var m = Movie("Stackoverflow: the movie"); 

Lưu ý rằng trong phương pháp thứ nhất và thứ ba, bạn có thể sử dụng các thành viên và phương pháp truy cập riêng. Nhưng lưu ý rằng to use this within private methods some must happen.

0

Bằng cách sử dụng chức năng tự thực hiện ẩn danh, bạn có thể cho phép các thuộc tính/phương pháp công khai và riêng tư.

Đây là mô hình tôi thích nhất:

(function ($, MyObject, undefined) { 

    MyObject.publicFunction = function() { 
     console.log("Public function"); 
    }; 

    var privateFunction = function() { 
     console.log("Private function"); 
    };  

    var privateNumber = 0; 
    MyObject.sayStuff = function() { 
     this.publicFunction(); 
     privateFunction(); 
     privateNumber++; 
     console.log(privateNumber); 
    }; 


    // You can even nest the namespaces 
    MyObject.nestedNamespace = MyObject.nestedNamespace || {}; 
    MyObject.nestedNamespace.logNestedMessage = function() { 
     console.log("Nested namespace function"); 
    }; 

}(jQuery, window.MyObject = window.MyObject || {})); 

MyObject.sayStuff(); 
MyObject.sayStuff(); 
MyObject.nestedNamespace.logNestedMessage(); 
MyObject.publicFunction(); 

học kinh nghiệm về nó từ những ý kiến ​​herethis article.

Các vấn đề liên quan