'this'返回数组而不是字符串。的JavaScript

时间:2019-01-23 10:10:44

标签: javascript arrays this

我正在阅读“ 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]}`)
})

我错过了什么或不了解什么?为什么相同的代码给出不同的结果?

3 个答案:

答案 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。然后您会看到thisid具有不同的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]”