【问题标题】:strict mode return this w/o violation严格模式返回此无违规
【发布时间】:2018-09-22 07:27:11
【问题描述】:

我也想吃蛋糕:我想有一个方法,它在绑定到对象时返回this 用于链接,但在使用空|未定义范围调用时返回undefined。这似乎工作正常,但如果你把它放入JSLint,那么你会得到一个严格的违规错误。我不需要使用严格模式,但似乎这应该是可能的和it works(打开控制台)。这可以吗和/或您还可以如何实现这种效果?

var o = {}; // or some pre-existing module
o.meth = (function (undefined) {

    // contrived example where you'd want to be able to locally 
    // access `meth` even if the outer `o.meth` was overwritten

    'use strict';

    var hash = Object.create(null); // "object" with no properties

    // global ref - or `null` where strict mode works
    var cantTouchThis = (function () {
        return this; 
    }).call(null);

    function meth (k, v) {
        var n;
        if (typeof k == 'object') { // set multi
            for (n in k) {
                meth(n, k[n]);
            }
        } else {
             if (v === undefined) { return hash[k]; } // get
             hash[k] = v; // set
        }
        if (this == cantTouchThis) { return; }
        return this;
    }

    return meth;

}());

如果你查看控制台:

var localM = o.meth; // now scopeless
console.log(  o.meth('key', 'val')  ); // should return `o`
console.log(  localM('key', 'val')  ); // should return `undefined`

【问题讨论】:

  • 有人说 undefined 不应该以这种方式进行比较(== 或 ===),因为它可以在您或第三方代码的某处重新定义。这样做当然是个坏习惯。
  • @PiotrSalaciak 是的,为了这个问题,我假设环境干净。我刚刚添加了undefined tho 作为你的第一个参数(这将是=== undefined b/c 它是用零参数调用的;)另一种安全的方法是比较=== void 0。

标签: javascript this ecmascript-5 strict-mode


【解决方案1】:

这几乎可以满足您的需求。

dontTouchThis 在支持“use strict”指令的环境中将是null,并在不支持它的环境中引用全局对象。

首先,您可以将 .call(null) 块替换为 (function(){return this})();它或多或少会产生相同的效果。

第二,不要忘记有 4 种方法可以调用函数,当涉及到 this 值时:作为方法、作为独立(无基础)函数、通过调用/应用和 new操作员。这意味着:

  • new (o.meth) 将返回 o
  • o.meth.call(o2, ...) 将返回 o2
  • o.meth.call(null, ...) 将返回 undefined

最后,如果有人将meth 别名为全局变量,那么在支持严格模式的环境中meth() 将返回全局对象,而不是undefined,因为cantTouchThis(即null)不会返回等于this(将引用全局对象)。

// in global scope

var meth = o.meth;
meth(...); // `this` references global object, will return global object

(function() {

  // in local scope
  var meth = o.meth;

  meth(...); // `this` is `undefined`, will return `undefined`

})();

【讨论】:

  • 谢谢/是的,这有帮助。我猜在严格模式下root = this || window 也是闭包内的一个选项,如果你知道它在全局范围内被调用的话。或root = (function(){return this}) || window。或者将单独的引用保存到根 this 和 window 以确保安全。你可以看到我在 @github.com/ryanve/hook
【解决方案2】:

为了安全起见,我最终使用了一个本地函数来“接地”范围解析:

var gnd = (function () {
    var globe = this || window;
    return function (o) {
        // for grounding (securing) scope
        return o == null || o === globe ? 0 : o;
    };
}());

查看用法in the source here。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    • 1970-01-01
    • 1970-01-01
    • 2020-03-22
    • 2013-08-10
    • 2017-02-25
    • 2012-07-24
    相关资源
    最近更新 更多