“使用严格”导致未定义的错误
Posted
技术标签:
【中文标题】“使用严格”导致未定义的错误【英文标题】:"use strict" causes undefined error 【发布时间】:2012-10-27 04:15:43 【问题描述】:我在我的 javascript 中定义了以下函数:
function _snr(id)
"use strict";
this.e = "something";
我通过 JSLint 运行我的代码,它建议我在函数中添加“use strict”。
当我执行e
现在会抛出未定义的错误。从一些初步调查来看,似乎不再定义用于引用 _snr
的 this
。
我已阅读有关“使用严格”的信息,并发现它用于防止不安全的做法。有人能解释一下这有什么不安全的吗? “使用严格”实际上在做什么以及如何修复我的代码?
【问题讨论】:
是什么让您认为this
会引用_snr
? this
的值取决于您调用函数的方式。如果你正在做_snr(123)
,那么this
将是全局对象,除非在严格模式下,它将是undefined
。
我想这是假设您正在使用this
访问全局,这对 JSLint 来说是一个禁忌。当然,如果你使用的是new _snr
,那就不是这样了。
严格模式目前在网络上几乎没用,关闭任何可以阻止 JSLint 说的选项。如果编写代码以使用严格模式功能,则在未实现它的浏览器中将失败。如果它没有利用严格模式,那么包含它是没有意义的(并且可能有害,正如您所发现的那样)。
@user1689607 我是 js 的菜鸟,如果我错了,请原谅我,但是当我在浏览器检查器中查看 this
时,它指的是 snr
,我错过了什么吗?
@Asad,那么我将如何访问全球?还是我根本不应该这样做?
【参考方案1】:
如果调用函数时未设置其this
,则在非严格模式下,其this
将设置为引用全局(浏览器中的窗口)对象。在严格模式下,它将保持未定义。
如果你的函数被称为_snr(...)
,那么它的this
没有设置,所以在非严格模式下this
将被设置为全局对象,所以this.e = ...
引用(或由于分配而创建)全局 e
属性。
但是,在严格模式下,this
将是未定义的,并且尝试访问未定义的属性会引发错误。
在ECMA-262 §10.4.3 Entering Function Code中有解释。
编辑
如果您希望以与严格模式和非严格模式一致的方式从函数内部访问全局对象,您可以使用类似的方式:
var _snr = (function(global)
return function (id)
global.e = "something";
;
(this));
在非严格模式下,你可以这样做:
function _snr(id)
var global = (function()return this;());
global.e = "something";
所以函数中的global
引用全局对象,您不必担心函数是如何被调用的。但是第二个例子在严格模式下不起作用。
其他答案:
我已阅读有关“使用严格”的信息,并发现它用于防止不安全的做法。有人能解释一下这有什么不安全的吗?
在这种特殊情况下绝对没有。
但是,在更一般的情况下,能够在阻止它直接访问全局对象的上下文中执行代码被认为是一个好主意。上面的第二个示例显示了如何在非严格代码中完成此操作(即如何从函数上下文中直接访问全局对象)。
“使用严格”实际上在做什么
如果调用将this
设置为undefined
或null
,它将停止将this
设置为全局对象。其后果见上文。
以及如何修复我的代码?
见上文。
哦,最后,ECMA-262 Annex C The Strict Mode of ECMAScript 中有一个关于严格模式的信息总结。
【讨论】:
@ferics2 这只是一种可怕的做法,它有可能毁掉每个人的一天。两个例子:1)创建一个构造函数并在没有new
的情况下调用它——而不是返回一个对象,构造函数将对象的值写入全局属性。 2) 函数内部的回调/函数——你认为this
指的是一个对象、外部函数的作用域或一个DOM 节点……相反,它指的是window
。而不是程序吐出你搞砸的错误,它只是写入/覆盖/读取window
属性并继续运行,就像一切都很顺利。
@ferics2——这意味着你可以防止say XHR加载的随机代码访问全局对象并重新定义你的全局变量。还有其他方法可以解决这个问题,但如果你需要的话,收紧this
会很方便。试试 Nicholas C. Zakas 的 It’s time to start using JavaScript strict mode。以上是关于“使用严格”导致未定义的错误的主要内容,如果未能解决你的问题,请参考以下文章
即时窗口中的动态导致“Microsoft.CSharp.RuntimeBinder.Binder”未定义或导入错误