我正在阅读“ JavaScript忍者的秘密,第二版”,其中包含以下代码:
function forEach(list,callback) {
for (var n = 0; n < list.length; n++) {
callback.call(list[n],n);
}
}
var weapons = ['shuriken','katana','nunchucks'];
forEach(weapons, function(index){
assert(this == weapons[index],
"Got the expected value of " + weapons[index]);
});
根据书,这似乎还可以。当发生“断言”时,“ this”作为字符串返回。
但是,当我自己运行代码时,“ this”作为字符数组返回。
0: "a"
1: "x"
2: "e"
length: 3
这是我的代码副本,this.toString()
进行了少许更改,并且与书中的内容一样(希望...)
function forEach(list, callback) {
for (let n = 0; n < list.length; n++) {
callback.call(list[n], n);
}
}
let weapons = [
'axe',
'sword',
'mace'
];
forEach(weapons, function (index) {
console.assert(this.toString() === weapons[index], `Got the expected value of ${weapons[index]}`)
})
我错过了什么或不了解什么?为什么相同的代码给出不同的结果?
答案 0 :(得分:0)
“但是当我自己运行代码时,'this'作为字符数组返回。”
它不是数组,而是String
实例。
将Function.prototype.call
与原始值thisArgument
一起使用时,将自动装箱(请参见spec)
6.b.i将此thisValue设为ToObject(thisArgument)。
如果您使用严格比较(===
)类型,则不会强制使用,因此new String('a') === 'a'
会得出false。
function forEach(list, callback) {
for (var n = 0; n < list.length; n++) {
callback.call(list[n], n);
}
}
var weapons = ['shuriken', 'katana', 'nunchucks'];
forEach(weapons, function(index) {
console.log(typeof this, this instanceof String) //object true
console.assert(this === weapons[index],
"Got the expected value of " + weapons[index]);
});
答案 1 :(得分:0)
那是一段非常有趣的代码,我将寻找这本书。首先,如何实现 assert 方法?假设如何实现 assert 方法,我做了一个小的代码块。
forEach
函数中代码的重要部分是callback.call
方法。如果您查看documentation:
function.call(thisArg,arg1,arg2,...) thisArg 可选的。此值提供给函数调用。请注意,这可能不是该方法看到的实际值:如果该方法是非严格模式下的函数,则将null和undefined替换为全局对象,并将原始值转换为对象。
本质上,this
成为list
中的值,在这种情况下为每个单词。您还提到了
自己运行代码“ this”作为字符数组返回
这是一个字符串,它是一个字符数组。在字符串中,您可以执行nameOfStringVar[index]
,然后您将获得该字符的位置。
console.log("hello"[1]);
它不是数组,而是String实例。另外,根据documentation,您将强制与===
进行类型比较。
三倍等于(===)将进行相同的比较(包括对NaN,-0和+0的特殊处理),但无需类型转换,只要类型不同,只需始终返回false即可。
但是人们会想,如果this
应该被列出[n] ,那===
会不会和list[n]
一样吗?
我假设在幕后JS正在根据传递的值创建一个新对象,这就是为什么'==='返回false的原因。我在输入时正在搜索此字词,如果我发现任何特定内容,我将编辑此答案。
我想到了以下几点,我使用mauke's piece of code向创建的每个对象添加了一个ID。然后您会看到this
与id
具有不同的weapons[index]
。
var enchant = (function () {
var k = 'id';
var uniq = 0;
return function enchant(o) {
var t = uniq++;
o[k] = function () {
return this === o ? t : enchant(this, k);
};
return t;
};
}());
enchant(Object.prototype);
function forEach(list,callback) {
for (var n = 0; n < list.length; n++) {
callback.call(list[n],n);
//list[n] is the new this, essentially the word
}
}
function assert(expression, message){
if(expression)
console.log(message);
else
console.log("Not equal");
}
var weapons = ['shuriken','katana','nunchucks'];
forEach(weapons, function(index){
console.log("this id is --> " + this.id());
console.log("weapoins[index] id is --> " + weapons[index].id());
assert(this == weapons[index],
"Got the expected value of " + weapons[index]);
});
function forEach(list,callback) {
for (var n = 0; n < list.length; n++) {
callback.call(list[n],n);
//list[n] is the new this, essentially the word
}
}
function assert(expression, message){
if(expression)
console.log(message);
else
console.log("Not equal");
}
var weapons = ['shuriken','katana','nunchucks'];
forEach(weapons, function(index){
assert(this == weapons[index],
"Got the expected value of " + weapons[index]);
});
答案 2 :(得分:-1)
由于未定义索引,因此无法使用。仅当使用native JS method for array(Array.forEach())时,才能将index作为参数传递。在您的情况下,“ this”将引用全局对象“ Window”,因此,如果对其进行字符串化,则会得到“ [object Window]”