在 Javascript 中,如何在不更改函数的情况下检查函数是否处于严格模式*?
In Javascript, how can I check if a function is in strict mode *without changing the function*?
我想编写一个测试套件以确保某些给定函数使用严格模式。有很多,手动检查它们似乎是一件苦差事。
An answer in a similar question 在函数定义上使用正则表达式进行检查。但是,我相信这会误检测被测试函数位于带有 "use strict" 或文件级 "use strict" 声明的函数内的情况。答案说 "use strict" 是前置的,但在我的环境(Mozilla Rhino)中,情况并非如此:
$ cat strict_sub.js
"use strict";
var strict_function = function() {
not_a_real_global = "foo";
};
print(strict_function);
$ rhino strict_sub.js
function () {
not_a_real_global = "foo";
}
我觉得答案是"no",但是有没有办法反省一个函数,看看它是否被解析并发现是严格模式?
更新:@Amy 建议的一种方法是解析函数的源代码以找出它。如果 function 有一个 use-strict 声明(虽然它很乏味),但如果严格模式是从程序级传播的,则此方法无效;在这种情况下,我们必须将 AST 提升到程序级别并检查 that 是否为 use strict
。为了使其健壮,我们必须实施所有 use strict
-传播规则,解释器已经在某处实现了这些规则。
(在 SpiderMonkey 中测试:
function f() {
"use strict";
}
var fast1 = Reflect.parse(f.toString());
var first_line = fast1.body[0].body.body[0].expression;
print(first_line.type === 'Literal' && first_line.value === 'use strict'); //true
)
严格模式函数确实有一个 "poisoned" .caller
and .arguments
properties (also ES5, extra),所以你可以测试一下:
function isStrict(fn) {
if (typeof fn != "function")
throw new TypeError("expected function");
try {
fn.caller; // expected to throw
return false;
} catch(e) {
return true;
}
}
我想编写一个测试套件以确保某些给定函数使用严格模式。有很多,手动检查它们似乎是一件苦差事。
An answer in a similar question 在函数定义上使用正则表达式进行检查。但是,我相信这会误检测被测试函数位于带有 "use strict" 或文件级 "use strict" 声明的函数内的情况。答案说 "use strict" 是前置的,但在我的环境(Mozilla Rhino)中,情况并非如此:
$ cat strict_sub.js
"use strict";
var strict_function = function() {
not_a_real_global = "foo";
};
print(strict_function);
$ rhino strict_sub.js
function () {
not_a_real_global = "foo";
}
我觉得答案是"no",但是有没有办法反省一个函数,看看它是否被解析并发现是严格模式?
更新:@Amy 建议的一种方法是解析函数的源代码以找出它。如果 function 有一个 use-strict 声明(虽然它很乏味),但如果严格模式是从程序级传播的,则此方法无效;在这种情况下,我们必须将 AST 提升到程序级别并检查 that 是否为 use strict
。为了使其健壮,我们必须实施所有 use strict
-传播规则,解释器已经在某处实现了这些规则。
(在 SpiderMonkey 中测试:
function f() {
"use strict";
}
var fast1 = Reflect.parse(f.toString());
var first_line = fast1.body[0].body.body[0].expression;
print(first_line.type === 'Literal' && first_line.value === 'use strict'); //true
)
严格模式函数确实有一个 "poisoned" .caller
and .arguments
properties (also ES5, extra),所以你可以测试一下:
function isStrict(fn) {
if (typeof fn != "function")
throw new TypeError("expected function");
try {
fn.caller; // expected to throw
return false;
} catch(e) {
return true;
}
}