【问题标题】:What's the purpose of Object(this) in javascript?javascript中Object(this)的目的是什么?
【发布时间】:2019-11-21 17:31:11
【问题描述】:

研究MDN web docs上写的find方法的polyfill,有一段我没有关注,让我分享代码

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    value: function(predicate) {
      if (this == null) {
        throw TypeError('"this" is null or not defined');
      }

      var o = Object(this);

      var len = o.length >>> 0;

      if (typeof predicate !== 'function') {
        throw TypeError('predicate must be a function');
      }

      var thisArg = arguments[1];

      var k = 0;

      while (k < len) {
        var kValue = o[k];
        if (predicate.call(thisArg, kValue, k, o)) {
          return kValue;
        }
        k++;
      }

      return undefined;
    },
    configurable: true,
    writable: true
  });
}

我的问题是表达式var o = Object(this);。这样做而不是var o = this 的目的是什么?在两种描述的情况下打印值都会返回相同的对象。

这是调用var o = new Object(this); 的缩写方式吗?

我已经从方法中删除了 cmets 以缩短文本,这里是 polyfill 实现的链接。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find#Polyfill

谢谢!

【问题讨论】:

  • 你的答案在前面的评论中:// 1. Let O be ? ToObject(this value).

标签: javascript


【解决方案1】:

在严格模式下,this 并不总是一个对象。 Object(this) 确保 o 是一个对象,而不是原语。

下面是一个this 是一个原语的例子:

"use strict";

Object.defineProperty(String.prototype, "nishCap", {
    writable: true,
    configurable: true,
    value() {
        console.log(typeof this); // "string"
        const o = Object(this);
        console.log(typeof o);    // "object"
        return o.substring(0,1).toUpperCase() + o.substring(1);
    }
});
const capped = "foo".nishCap();

请注意,这甚至适用于数组方法,因为您可以在非数组上调用它们,例如 Array.prototype.find.call("foo", ch =&gt; ch === "o")

这是调用var o = new Object(this); 的缩写方式吗?

不,new Object 总是创建一个新对象(并且不使用您给它的参数)。当您call Object as a function 时,它会将其参数强制为对象。所以原始字符串变成String对象,原始数字变成Number对象,等等。

这样做而不是var o = this的目的是什么?

那个 polyfill 非常接近 the spec,它的开头是:

  1. 让 O 成为? ToObject(此值)。

在大多数情况下,它并不重要,但如果在某些极端情况下忽略它会导致可观察到的行为与规范不一致,我不会感到惊讶。

【讨论】:

  • 我必须熟悉规范文档中使用的语言。我知道我从那些 cmets 中遗漏了一些东西,谢谢。
  • @jcamejo - 这需要一些时间来适应!特别是在规范操作之前使用!(描述为here)。它意味着否定。有时很难读过去... :-)
【解决方案2】:

因为Array.prototype.find 可以使用this 值调用,该值不是一个对象。见specification

当调用find方法时,会采取以下步骤:

  1. 让 O 成为? ToObject(此值)。

所以,为了完全符合规范,polyfill 需要Object(this)。否则实现会不一样,通过下面两个sn-ps可以看出:

'use strict';
const str = 'abc';
Array.prototype.find.call(
  str,
  (char, i, theThis) => {
    // theThis should be an object, even if called on a non-object:
    console.log(theThis);
  }
);

'use strict';
Object.defineProperty(Array.prototype, 'find', {
  value: function(predicate) {
    if (this == null) {
      throw TypeError('"this" is null or not defined');
    }

    // Without object wrapping:
    var o = this; // <-------------------------------

    var len = o.length >>> 0;

    if (typeof predicate !== 'function') {
      throw TypeError('predicate must be a function');
    }

    var thisArg = arguments[1];

    var k = 0;

    while (k < len) {
      var kValue = o[k];
      if (predicate.call(thisArg, kValue, k, o)) {
        return kValue;
      }
      k++;
    }

    return undefined;
  },
  configurable: true,
  writable: true
});


const str = 'abc';
Array.prototype.find.call(
  str,
  (char, i, theThis) => {
    // The polyfill above had no object wrapping, so this result is not the same:
    console.log(theThis);
  }
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 2012-07-28
    • 2011-09-13
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多