【问题标题】:How are array methods aware of the values they are called on?数组方法如何知道它们被调用的值?
【发布时间】:2019-09-13 20:59:18
【问题描述】:

有人可以向我解释一下数组方法是如何知道我们调用它们的值的吗? 作为原型继承的一部分,它不应该存在于 Array.prototype 如果我们说

let animals = ['dog','cat']
animals.map( x => console.log(x))
//dog
//cat

我只是不明白 map 是如何知道我们通过了 ['dog','cat'] 的。 我通常看到,如果你调用一个函数,那么你需要像 map(animals) 一样调用它。

提前谢谢你

或查看地图 polyfill,我们将其分配给数组参数的行在哪里。

if (!Array.prototype.map) {

  Array.prototype.map = function(callback/*, thisArg*/) {

    var T, A, k;

    if (this == null) {
      throw new TypeError('this is null or not defined');
    }


    var O = Object(this);


    var len = O.length >>> 0;

    // 4. If IsCallable(callback) is false, throw a TypeError exception.
    // See: http://es5.github.com/#x9.11
    if (typeof callback !== 'function') {
      throw new TypeError(callback + ' is not a function');
    }


    if (arguments.length > 1) {
      T = arguments[1];
    }


    A = new Array(len);

    // 7. Let k be 0
    k = 0;

    // 8. Repeat, while k < len
    while (k < len) {

      var kValue, mappedValue;


      if (k in O) {

        // i. Let kValue be the result of calling the Get internal 
        //    method of O with argument Pk.
        kValue = O[k];


        mappedValue = callback.call(T, kValue, k, O);



        // For best browser support, use the following:
        A[k] = mappedValue;
      }
      // d. Increase k by 1.
      k++;
    }

    // 9. return A
    return A;
  };
}

【问题讨论】:

  • 这是 JavaScript 原型继承的魔力,再加上在函数调用中如何设置 this 的规则。
  • 为什么要否决这个问题?
  • Array​.prototype​.map() 与分配给对象的任何其他方法没有什么不同。 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…arr.map(function callback(currentValue[, index[, array]]) {
  • 你知道普通方法如何知道它们被调用的对象吗?喜欢obj.f() 上的const obj = { x: 1, f() { console.log(this); }};
  • @JSLover 为什么参数会改变 this 在方法中指向的内容?

标签: javascript


【解决方案1】:

Array.prototype.mymap = function(callback) {
	var myArray = this; // here is the magic
	var newArray = [];
	for (var i = 0; i < myArray.length; i++) {
		newArray.push(callback(myArray[i]));
	}
	
	return newArray;
};

console.log([0, 1, 2, 3].mymap(a => a * 2));

【讨论】:

  • 所以如果我正在查看实际的地图多边形填充,您能否像在此处一样指出神奇的位。 var O = Object(this);
  • @JSLover Object() 调用通常什么都不做,你也可以写成var O = this;。当对原始(非对象)值(例如字符串)调用该方法时,它会处理边缘情况。
【解决方案2】:

如果我们根据 W3Schools 查看 Map 的定义:

map() 方法使用调用的结果创建一个新数组 每个数组元素的函数。

因此,函数 map 会检查每个元素并对其进行处理。 在此示例中,您说:“Console.log 此数组中的每个元素”

因此,函数映射知道数组中的内容是逻辑。

【讨论】:

    【解决方案3】:

    map()Array 对象的一个​​方法。在 JavaScript 中,我们说animals 对象使用Array 对象的“原型继承”。这有点像说animals 继承了Array 基类的属性和方法(如果您来自OOP 世界)。

    由于map 是一个适用于所有Array 对象的函数,animals 也不例外。

    根据定义map() 接受一个函数,并返回一个Array。然后它遍历调用它的数组的每个元素(在本例中为animals 数组),并将传递的函数应用于每个元素。

    通常您会将其与return 语句一起使用以生成新数组。例如,您可以编写如下内容:

    var upperCaseAnimals = animals.map(x =&gt; return(x.toUpperCase()))

    这将创建一个新数组upperCaseAnimals,其中包含animals 数组的所有元素,并应用了toUpperCase()

    但您也可以使用它对数组的每个元素“做某事”。这就是上面示例中所做的。您无需为每个元素提供返回值,而是 console.log()ing 每个元素。

    【讨论】:

    • 第一段错误。它试图简化继承,但......没有必要。 animals is 数组 - 继承与行为无关。最后一句话,如果转移到 Java 中会读到“当你做 Person p = new Person() 时,p 继承了基础 Person 类的方法”,这不是那里发生的事情,也不是这里发生的事情。 p is Person 并且 具有 所有方法,不继承它们。同样,animals 一个数组。继承将与子类一起发挥作用。
    • animals 不是数组。 animals 是它自己的对象。 JavaScript 没有类型。您无法与 Java 进行比较,因为 Java 确实有类型。 JavaScript 中没有“类”之类的东西。
    • 我不同意 Array.isArray(animals) 将返回 true 因为它是一个数组。它和p 一样都是“它自己的对象”——两者都是instances。您似乎在这里混淆了类和实例。
    • Array.isArray(animals) 检查是否为animals.Prototype === 'Array'。不信可以自己查JS源码^^
    • 顺便说一句,我为此苦苦挣扎了很长时间。这个帖子真的帮助我理解了stackoverflow.com/questions/3450781/…
    猜你喜欢
    • 1970-01-01
    • 2018-12-15
    • 1970-01-01
    • 2010-12-14
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多