I saw here Array.prototype.forEach()
的polyfill,我对其实施有疑问:
/*1*/ if (!Array.prototype.forEach)
/*2*/ {
/*3*/ Array.prototype.forEach = function(fun /*, thisArg */)
/*4*/ {
/*5*/ "use strict";
/*6*/
/*7*/ if (this === void 0 || this === null)
/*8*/ throw new TypeError();
/*9*/
/*10*/ var t = Object(this);
/*11*/ var len = t.length >>> 0;
/*12*/ if (typeof fun !== "function")
/*13*/ throw new TypeError();
/*14*/
/*15*/ var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
/*16*/ for (var i = 0; i < len; i++)
/*17*/ {
/*18*/ if (i in t)
/*19*/ fun.call(thisArg, t[i], i, t);
/*20*/ }
/*21*/ };
/*22*/ }
看第10行:为什么他们使用Object(this)
?
当我搜索它的用法时,我看到了this:
Object构造函数为给定值创建一个对象包装器。 如果值为null或未定义,则会创建并返回空值 对象,否则,它将返回对应类型的对象 到给定的值。如果该值已经是一个对象,它将返回 价值。
所以他们想检查一下null
|| undefined
。
好的, 但是他们已经在#7-#8行中进行了检查!
问题:
他们使用Object(this)
的原因(我错过了)是什么原因?
答案 0 :(得分:2)
所以他们想检查它是否为空||未定义。
没有。目的是
Object构造函数为给定值创建一个对象包装器。 如果值为null或未定义,则将创建并返回空值 对象,否则,它将返回一个类型的对象 对应于给定值。如果值已经是对象, 它会返回值。
它会将基元转换为对象,例如"foo"
到new String("foo")
。
这绝对不是必需的,因为.length
和索引的属性访问无论如何都会将基元转换为对象。然而,当使用第三个回调参数时,你可以期待一个对象(每个调用都有一个对象)。
他们使用
Object(this)
的原因是什么?
主要是重现forEach
spec的第1步,即在参数上调用ToObject
。在规范中,必须能够使用[[Get]]
和[[HasProperty]]
内部方法。
此外,只有在获得速度后才能将图元转换为对象。
答案 1 :(得分:1)
我正在寻找这个问题因为我为什么会这样徘徊。目前正确的答案让我没有达到100%的满意度。所以我试图执行代码,如果我删除了Object(这个)并且只是var O = this;可以在此处找到forEach函数的定义:ECMAScript forEach。因此,您可以看到为什么会创建变量以及名称等等。多面体尽可能精确。
由于OP想要只知道对象(这个),我将关注它。我找到了为什么需要这样做的原因。试试这段代码:
Array.prototype.forEach.call("abc", func);
基本上我们循环遍历abc字符串。 Object(this)使abc成为:
String {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}
如果我们不这样做,abc将只是简单的&#34; abc&#34;。然后在polyfill的循环中我们这样做:
kValue = O[k];
对于&#34; abc&#34;这将获得字符串的每个字母。但是这不起作用,并且会在IE&lt; 8。
上给出未定义的内容为什么这不起作用在其他问题的引用中解释: &#34;此表示法在IE7中不起作用。第一个代码片段将在IE7中返回undefined。如果您碰巧在代码中使用括号表示字符串,并且想要迁移到.charAt(pos),这真是一个痛苦的问题:代码中使用的是括号,并且没有简单的方法可以检测到如果是字符串或数组/对象的话。&#34; (source)
但是当使用Object(this)时,这将没有问题。
我发现的另一个引用方便:
&#34;注意forEach函数是有意通用的;它不要求它的这个值是一个Array对象。因此,它可以转移到其他类型的对象以用作方法。 forEach函数是否可以成功应用于宿主对象是依赖于实现的。&#34; (source)
答案 2 :(得分:0)
目的不是检查未定义。相反,它是处理原语。
例如,如果this
是42
之类的数字,那么它将是Object(42)
,这是Number
个对象,其值为42
}。
这意味着您可以将输入视为一个对象,即使它原来是一个原语。
要进行测试,请尝试在字符串上使用polyfill - 字符串具有.length
属性。举个例子,试试......
[].forEach.call("Hello!",function(letter) {console.log(letter);});