2009-09-17 53 views
28

thể trùng lặp:
Use of 'prototype' vs. 'this' in Javascript?chức năng dụ Javascript so với chức năng nguyên mẫu

sự hiểu biết của tôi về các loại khác nhau của các hàm JavaScript như sau:

function MyObj() { 
    this.propOne = true; 
    this.publicInstanceFunc = function() { 
     if (propOne) 
      return 'public instance function'; 
    } 
    function privateFunc() { 
     return 'private function only visible inside this constructor'; 
    } 
} 

MyObj.prototype.protoFunc = function() { 
    if (this.propOne) 
     return 'prototype function shared amongst all instances of MyObj'; 
} 
  1. Are những điều này đúng không?
  2. Trong trường hợp nào người ta nên đặt các chức năng trên nguyên mẫu (ví dụ: protoFunc) và trong hàm tạo (ví dụ: publicInstanceFunc)?
  3. Đang sử dụng this cách chính xác để truy cập các thuộc tính bên trong các hàm nguyên mẫu?

Trả lời

49

Bạn thực sự có thể thêm một mức độ đặc quyền thông qua gói toàn bộ điều trong một chức năng tự thực hiện:

var MyObj = (function() { // scoping 
    var privateSharedVar = 'foo'; 

    function privateSharedFunction() { 
     // has access to privateSharedVar 
     // may also access publicSharedVar via explicit MyObj.prototype 
     // can't be called via this 
    } 

    function MyObj() { // constructor 
     var privateInstanceVar = 'bar'; 
     this.publicInstanceVar = 'baz'; 

     function privateInstanceFunction() { 
      // has access to all vars 
      // can't be called via this 
     }; 

     this.publicInstanceMethod = function() { 
      // has access to all vars 
      // also known as a privileged method 
     }; 
    } 

    MyObj.prototype.publicSharedVar = 'quux'; 

    MyObj.prototype.publicSharedMethod = function() { 
     // has access to shared and public vars 
     // canonical way for method creation: 
     // try to use this as much as possible 
    }; 

    return MyObj; 
})(); 

Chỉ tính 'cộng đồng' có thể được truy cập từ bên ngoài thông qua this. Đối với lý do hiệu suất, bạn nên tránh những gì tôi gọi là phương pháp 'dụ': Đối với mỗi trong số này, một đối tượng hàm mới phải được tạo cho mỗi cá thể MyObject, trong khi chỉ có một đối tượng hàm duy nhất cho mỗi phương thức 'được chia sẻ'.

+0

Cảm ơn! Câu trả lời hay! – mcjabberz

+0

xin lỗi để hồi sinh câu hỏi/câu trả lời này, nhưng không bao bọc chức năng bên ngoài trong parens làm bất cứ điều gì đặc biệt? ví dụ. như thế nào (function() {})(); khác với hàm() {}(); – Matt

+0

@Matt: các parens bên ngoài buộc hàm theo nghĩa đen được hiểu là biểu thức thay vì một câu lệnh; họ là không cần thiết trong trường hợp này bởi vì nhiệm vụ đã buộc sự giải thích này, nhưng nếu không có nó, bạn sẽ nhận được một lỗi cú pháp nếu bạn bỏ qua các parens – Christoph

3

1) Có mã của bạn là đúng.

2) Tôi sử dụng các hàm được định nghĩa trong hàm hàm dựng khi tôi muốn truy cập các thành viên khác được xác định riêng trong phạm vi hàm của hàm tạo, ví dụ, khi bạn muốn tạo privileged methods.

Chức năng công khai được xác định trên hàm hàm tạo, tốn kém tính toán hơn là thêm hàm đơn giản vào mẫu đối tượng, nhưng chúng cũng mang lại cho bạn sự linh hoạt hơn nhiều.

3) Có, nếu thuộc tính công khai, bạn có thể truy cập nó bằng cách sử dụng từ khóa this bên trong của hàm mở rộng mẫu thử, vì this là trường hợp đối tượng của bạn.

3

Về điểm thứ hai, bạn mở rộng nguyên mẫu sao cho tất cả các đối tượng đã tạo có phương pháp mới.

Ngoài ra, cho phép bạn thêm các phương thức vào đối tượng dựng sẵn (như thêm trim() đến string).

4

Chúng có đúng không?

Err. Vâng, nó phụ thuộc vào những gì bạn muốn làm. Không có ai chấp nhận mô hình kinh điển để thực hiện kế thừa kiểu lớp/cá thể trong JavaScript.

Nhưng điều này:

if (propOne) 

Có lẽ là một sai lầm, trong this.propOne đó là một tài sản của đối tượng chủ sở hữu, trong khi propOne bởi chính nó là một biến chưa được khai báo (giá trị mặc định này đến một biến toàn cầu, nhưng thường là một sai lầm).

Trong trường hợp nào bạn nên đặt chức năng trên mẫu thử nghiệm (ví dụ: protoFunc) so với hàm khởi tạo (ví dụ: publicInstanceFunc)?

Một chức năng được đặt trên nguyên mẫu là cùng một chức năng được chia sẻ giữa tất cả các đối tượng. Cách duy nhất nó có thể tìm ra ví dụ của nó là bằng cách đọc ‘this’ khi nó được gọi.

Một hàm được đặt trên ‘this’ trong hàm tạo là một hàm mới cho mọi phiên bản của MyObj. Bạn có thể sử dụng điều này như một cách khác để liên kết với đối tượng chủ sở hữu dựa trên các đóng cửa thay vì ‘this’, điều này có thể tiết kiệm được việc viết ra những thứ ràng buộc chức năng. Đó là một phong cách khác nhau của hướng đối tượng mà thông thường bạn sẽ không pha trộn với phong cách này dựa trên.

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