2012-01-29 28 views
7

tham khảo: http://ejohn.org/blog/simple-class-instantiation/John Resig của đơn giản lớp và "sử dụng nghiêm ngặt"

// makeClass - By John Resig (MIT Licensed) 
function makeClass(){ 
    return function(args){ 
    if (this instanceof arguments.callee) { 
     if (typeof this.init == "function") 
     this.init.apply(this, args.callee ? args : arguments); 
    } else 
     return new arguments.callee(arguments); 
    }; 
} 

tôi đã tự hỏi, nếu có bất kỳ ECMAScript 5 cách phù hợp để thực hiện các chức năng tương tự. Vấn đề là, việc truy cập arguments.callee sẽ không được chấp nhận ở chế độ nghiêm ngặt.

Trả lời

4

Vì tôi hiểu nó arguments.callee không phải là không được chấp nhận ở chế độ nghiêm ngặt, trong trường hợp này bạn có thể tiếp tục sử dụng; thay vào đó, nó đã bị xóa và việc sử dụng đã cố gắng (hoặc được cho là) ​​ném một ngoại lệ.

Cách giải quyết là sử dụng các hàm ẩn danh có tên, nếu bạn sẽ tha thứ cho oxymoron. Thực sự tôi nên nói "named function expressions". Một ví dụ:

function someFunc(){ 
    return function funcExpressionName(args){ 
    if (this instanceof funcExpressionName) { 
     // do something 
    } else 
     return new funcExpressionName(arguments); 
    }; 
} 

Tên bạn cung cấp, trong ví dụ của tôi funcExpressionName là không được phép có thể truy cập từ bất cứ nơi nào ngoại trừ bên trong hàm nó áp dụng cho, nhưng tiếc là IE có những ý tưởng khác (như bạn có thể thấy nếu bạn Google it) .

Ví dụ trong câu hỏi của bạn Tôi không biết cách xử lý args.callee vì tôi không biết cách thức được đặt bởi hàm gọi, nhưng việc sử dụng arguments.callee sẽ được thay thế theo ví dụ của tôi.

1

Mã gốc của John Resig không thành công với hàm tạo không tham số.

var Timestamp = makeClass(); 
Timestamp.prototype.init = function() { 
    this.value = new Date(); 
}; 

// ok 
var timestamp = Timestamp(); 
alert(timestamp.value); 

// TypeError: args is undefined 
var timestamp = new Timestamp(); 
alert(timestamp.value); 

Nhưng nó có thể được sửa chữa bằng cách sử dụng dòng sau

this.init.apply(this, args && args.callee ? args : arguments); 
2

Ý tưởng trên được đưa ra bởi nnnnnn là khá tốt. Và để tránh các vấn đề về IE, tôi đề xuất giải pháp sau đây.

function makeClassStrict() { 
    var isInternal, instance; 

    var constructor = function(args) { 
     // Find out whether constructor was called with 'new' operator. 
     if (this instanceof constructor) { 
      // When an 'init' method exists, apply it to the context object. 
      if (typeof this.init == "function") { 
       // Ask private flag whether we did the calling ourselves. 
       this.init.apply(this, isInternal ? args : arguments); 
      } 
     } else { 
      // We have an ordinary function call. 

      // Set private flag to signal internal instance creation. 
      isInternal = true;           
      instance = new constructor(arguments); 
      isInternal = false;           
      return instance; 
     } 
    }; 

    return constructor; 
} 

Lưu ý cách chúng tôi tránh tham chiếu đến args.callee trong phần // do something bằng cách sử dụng cờ nội bộ.

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