Câu trả lời:
Tôi đã thêm một bài kiểm tra jsperf cho 4 cách khác nhau để tạo một hàm từ chuỗi:
Sử dụng RegExp với lớp chức năng
var func = "function (a, b) { return a + b; }".parseFunction();
Sử dụng lớp Chức năng với "return"
var func = new Function("return " + "function (a, b) { return a + b; }")();
Sử dụng hàm tạo hàm chính thức
var func = new Function("a", "b", "return a + b;");
Sử dụng Eval
eval("var func = function (a, b) { return a + b; };");
Cách tốt hơn để tạo một hàm từ một chuỗi là sử dụng Function
:
var fn = Function("alert('hello there')");
fn();
Điều này có ưu điểm / nhược điểm là các biến trong phạm vi hiện tại (nếu không phải là toàn cục) không áp dụng cho hàm mới được xây dựng.
Việc chuyển đối số cũng có thể:
var addition = Function("a", "b", "return a + b;");
alert(addition(5, 3)); // shows '8'
Function
bạn không gây ô nhiễm phạm vi cục bộ và đây là lý do tại sao eval
việc tối ưu hóa rất khó khăn cho các động cơ ... Với ví dụ OP, tôi sẽ:var fnc = Function('return '+s)();
element.onclick = function() { alert("test"); }
.
Bạn khá gần gũi.
//Create string representation of function
var s = "function test(){ alert(1); }";
//"Register" the function
eval(s);
//Call the function
test();
Đây là một công việc khó khăn .
eval
Cảnh báo bắt buộc cho những người tìm kiếm trong tương lai: eval
có thể mở sơ hở cho tin tặc: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… nhưng nếu bạn biết những nguy hiểm của nó và có thể tránh chúng, thì đây là một cách đơn giản hay để tạo một hàm từ một chuỗi
Vâng, sử dụng Function
là một giải pháp tuyệt vời nhưng chúng ta có thể đi xa hơn một chút và chuẩn bị trình phân tích cú pháp phổ quát để phân tích cú pháp chuỗi và chuyển đổi nó thành hàm JavaScript thực ...
if (typeof String.prototype.parseFunction != 'function') {
String.prototype.parseFunction = function () {
var funcReg = /function *\(([^()]*)\)[ \n\t]*{(.*)}/gmi;
var match = funcReg.exec(this.replace(/\n/g, ' '));
if(match) {
return new Function(match[1].split(','), match[2]);
}
return null;
};
}
ví dụ về cách sử dụng:
var func = 'function (a, b) { return a + b; }'.parseFunction();
alert(func(3,4));
func = 'function (a, b) { alert("Hello from function initiated from string!"); }'.parseFunction();
func();
đây là jsfiddle
JavaScript
Function
var name = "foo";
// Implement it
var func = new Function("return function " + name + "(){ alert('hi there!'); };")();
// Test it
func();
// Next is TRUE
func.name === 'foo'
Nguồn: http://marcosc.com/2012/03/dynamic- Chức năng-names-in-javascript/
eval
var name = "foo";
// Implement it
eval("function " + name + "() { alert('Foo'); };");
// Test it
foo();
// Next is TRUE
foo.name === 'foo'
sjsClass
https://github.com/reduardo7/sjsClass
Class.extend('newClassName', {
__constructor: function() {
// ...
}
});
var x = new newClassName();
// Next is TRUE
newClassName.name === 'newClassName'
Kỹ thuật này cuối cùng có thể tương đương với phương thức eval, nhưng tôi muốn thêm nó, vì nó có thể hữu ích cho một số người.
var newCode = document.createElement("script");
newCode.text = "function newFun( a, b ) { return a + b; }";
document.body.appendChild( newCode );
Điều này có chức năng giống như thêm phần tử <script> này vào cuối tài liệu của bạn, ví dụ:
...
<script type="text/javascript">
function newFun( a, b ) { return a + b; }
</script>
</body>
</html>
Sử dụng new Function()
với trở lại bên trong và thực thi nó ngay lập tức.
var s = `function test(){
alert(1);
}`;
var new_fn = new Function("return " + s)()
console.log(new_fn)
new_fn()
Một ví dụ với các đối số động:
let args = {a:1, b:2}
, fnString = 'return a + b;';
let fn = Function.apply(Function, Object.keys(args).concat(fnString));
let result = fn.apply(fn, Object.keys(args).map(key=>args[key]))