Ghi chú thêm để gửi bài Cristian Sanchez'.
Bạn không bao giờ có thể truy cập vars phạm vi địa phương trong 'Đánh giá chức năng'.
Cho phép xem sự khác biệt giữa Hàm và eval.
Chức năng-Ví dụ:
var f, a = 1;
(function() {
var a = 123;
f = new Function("return a");
})();
console.log(f()) // 1
Chức năng-Constructor không biết gì về phạm vi địa phương, bởi vì nó tạo ra một Phạm vi cô lập mới bên dưới cửa sổ/toàn cầu-Object - không phải ở vị trí mà nó là - đó là sự khác biệt chính đối với eval.
Eval-Ví dụ:
var f, a = 1;
(function() {
var a = 123;
eval("f = function() { return a }");
})();
console.log(f()) // 123
'eval' có quyền truy cập vào các vars địa phương. Ngay cả khi bạn phạm vi toàn bộ điều.
var f, a = 1;
(function() {
var a = 123;
eval("f = (function() { function f() { return a }; return f; })();");
})();
console.log(f()) // still 123
Trong ví dụ sau f() throws một lỗi - "a" được định nghĩa trong phạm vi riêng (và thế giới) của mình. Function-Constructor có phạm vi đặc biệt riêng của nó mà không biết bất cứ điều gì bên ngoài - ngoại trừ phạm vi cha mẹ của bạn - cửa sổ/đối tượng toàn cầu.
delete a;
var f;
(function()
{
var a = 1;
f = new Function("return a");
})();
console.log(f()); // Throws error (a is not defined)
Nếu bạn muốn sử dụng các vars cục bộ, hãy chuyển nó làm tham số cho hàm-Constructor bên trong phạm vi bên trong!
var f, a = 1;
(function() {
var a = 123;
f = new Function("a", "return a");
console.log(f(a)); // passing inner a: result = 123
})();
console.log(f(a)); // passing outer a: result = 1
hoặc
var result, a = 1;
(function() {
var a = 123;
var f = new Function("a", "return a");
result = f(a); // store result in global var
})();
console.log(result); // 123
Bạn có thể thực hiện chức năng trực tiếp với cuộc gọi/áp dụng, quá (không "mới" cần thiết).
Function('a','b','c', 'console.log(c,b,a)').call(this, 1, 2, 3); // output: 3 2 1
Function('console.log(arguments)').apply(this, [1, 2, 3]); // access through arguments[0-3]
Bằng cách này, nó luôn luôn khuyên, thiết lập chế độ nghiêm ngặt, để cho phép hành vi ES5 chính xác.
Với chế độ nghiêm ngặt 'này' là (chính xác) không được xác định theo mặc định - cho đến khi bạn ràng buộc một đối tượng.
Function('console.log(this)')(); // this is 'window' in sloppy mode
Function('"use strict"; console.log(this)')(); // this is undefined - correct behavior
Nếu bạn muốn, bạn có thể liên kết 'này' một cách rõ ràng
// bind 'this' to 'window' again
Function('"use strict";console.log(this)').bind(window)();
// bind 'this' to an Object without __proto__
Function('"use strict";console.log(this)').bind(Object.create(null))();
Tất nhiên bạn có thể gắn bất kỳ chức năng/lớp đối tượng để mở rộng đối tượng.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
new Function('"use strict"; this.a = 5; this.b = 6;').bind(cls)();
console.log(cls.a); // a = 5 - override property
console.log(cls.b); // b = 6 - appended property
Cùng một kết quả với cuộc gọi trực tiếp, mà không cần khóa 'mới'.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
Function('"use strict"; this.a = 5; this.b = 6; this.foo = function(){console.log("bar")}').call(cls);
console.log(cls.a); // a = 5 - override property
console.log(cls.b); // b = 6 - appended property
console.log(cls.foo()); // bar - appended function
Mọi chức năng/lớp được tạo thông qua hàm tạo hàm 'Hàm'.
Vì vậy, bạn không phải viết "Chức năng" trong mã của mình. Bạn cũng có thể sử dụng đối tượng hàm tạo.
function SomeClass()
{
this.a = 1;
}
var cls = new SomeClass();
SomeClass.constructor("this.a = 2;").call(cls);
cls; // SomeClass {a: 2}, because "SomeClass.constructor" === Function
Việc sử dụng 'Chức năng' là tốt ví dụ cho các trò chơi, nếu bạn có một XMLHttpRequest-Preloader, mà tải một rất lớn Javascript Tệp (5-10 MB kèm script), trong khi bạn muốn hiển thị một tải-bar hoặc một cái gì đó khác cho người dùng, thay vì tải toàn bộ điều với một script-tag, trong khi người dùng đang chờ tải trang mà không có bất kỳ phản ứng trực quan nào.
Việc bạn tải tập lệnh lớn thông qua thẻ tập lệnh không quan trọng hay thông qua chức năng một lần khi khởi động. Động cơ phải nạp mã đơn giản và đánh giá nó theo một trong hai cách. Không có khía cạnh bảo mật, nếu mã (!) Của bạn đến từ một nguồn đáng tin cậy (tên miền của bạn) và bạn biết những gì bên trong.
'Chức năng' và 'eval' chỉ xấu với mã không đáng tin cậy (khi người dùng khác có ảnh hưởng đến nó) hoặc trong vòng lặp (biên dịch chậm hiệu suất), nhưng hoàn toàn không thể tải & đánh giá tập lệnh của riêng bạn khi khởi động , nếu mã giống như trong các tệp Javascript bên ngoài.
Xem: [Sử dụng hợp pháp của hàm tạo hàm] (http://stackoverflow.com/questions/3026089/legitimate-uses-of-the-function-constructor) – CMS
Video tốt về hàm javascript http: // developer. yahoo.com/yui/theater/video.php?v=crockonjs-3 – Thomas
@CMS @Thomas, Cảm ơn bạn đã liên kết. – c4il