在JavaScript中拳击强制?

时间:2015-12-03 13:26:35

标签: javascript

You Don't Know JS - the Coercion Chapter我已经读到了强制,你永远不会得到一个复杂值的结果,比如对象或数组。拳击在准确的意义上不被视为强制。如何在引擎盖后面的JavaScript与强制不同?我真的看不出表面上的任何差异。

3 个答案:

答案 0 :(得分:21)

这主要是语义问题。

首先,让我们定义“装箱”,因为这个术语在JavaScript中并不常用(例如,它没有出现在规范中):

“Boxing”将对象包裹在原始值周围。例如,new Number(42)为原始数字42创建Number对象。

在JavaScript中完成的唯一自动装箱是:

  1. 在基元上使用方法时,如下所示:

    console.log("testing".toUpperCase());
    

    "testing"是一个原始字符串,因此不会(也不能)拥有方法。当JavaScript引擎看到具有原始根的属性访问器操作时,根据规范,它会在检索属性之前为该原语(例如,原始字符串的String对象)创建包装器对象。如果正在调用该属性(例如,"foo".toUpperCase()),则在松散模式下,包装器对象在调用中为this(在严格模式下,它是原始字符串)。除非方法调用中的某些东西保留了包装器对象,否则它会被丢弃。

  2. 在松散模式下使用基元作为Function#callFunction#apply的第一个参数时,它会被设置为在调用期间为this。 (在严格模式下,this可以是原语。)除非被调用的函数保留对包装器对象的引用,否则在调用完成后它将被丢弃。

  3. 取消装箱当然是相反的:从拳击对象中获取原语。

    规范中的语言称为装箱“转换”:

    来自§7.1.13

      

    抽象操作ToObject 参数转换为Object类型的值...

    但是,它会将取消装箱称为“转化”和“强制”:

    来自§7.1.1

      

    抽象操作ToPrimitive 将其输入参数转换为非对象类型

    来自§4.3.16

      

    布尔对象可以强制为布尔值。

    来自§4.3.19

      

    String对象可以强制为String值...

    在一天结束时,重要的是我们了解什么时候会发生什么。我怀疑作者没有故意做出 convert coerce 之间的强烈区别。

答案 1 :(得分:1)

拳击强制是不同的事物,可以独立发生,也可以彼此独立发生,或者两者同时发生。

  • 拳击是在对象内部包装图元
  • 强制类似于将原语解释为另一种类型

如果看到装箱正在转换给定值的类型,那么转换* 装箱都是这样。

例如:

var sp = 'abc';              // string primitive

// boxing
var so = new String( sp );   // string object, created from string primitive

// first conversion* and then boxing
var sn = new String( 123 ); // string object, created from a number

// coercion without boxing
var n = '3' - 1;            // number 2

*)我不知道'3' - 1处的强制是否与new String( 123 )处的转换由JavaScript引擎的同一部分完成,但是我认为这样思考是有效的。 / p>

您可以使用拳击来做只能对对象执行的操作,例如:

var s = new String('a');
s.id = 123
// --> String { 0: "a", id: 123, length: 1 }

我从不需要显式地使用拳击,而只是隐式地例如在"abc".charAt(0)

(意见:)

无论如何,根据我的理解,胁迫一词用于强调一个事实,即隐式发生(在其他类型的上下文中),而不是强制转换或转换。那意味着永远不会有明确的强制!你真的不能强制。强制只是发生

但是可以使用强制规则来强制类型,例如:'' + 3实际上是字符串连接,但是由于隐式强制,可以将其用于转换。另一方面,+'3'Number('3')将是显式转换,而不是强制转换。 (规范似乎在这里没有明确区分。)

因此,以一种自以为是的方式重新表述以上内容:

  • 拳击是在对象内部包装图元
  • 强迫是会发生的事情,不是您可以做的事情。
  • 可以明确地进行转换,也可以利用拳击或强制转换

答案 2 :(得分:0)

T.J。人群提供正确的答案。只是要补充一点,术语“装箱”在JavaScript世界中通常不使用,并且规范不使用它,但它确实存在。将原始对象包装为对象是拳击的一种形式,YDKJS的凯尔·辛普森在他的演讲和书籍中都非常清楚,拳击是一种隐含的强制形式。

不幸的是,这种误解是仍然经常遇到“一切都是JavaScript中的对象”这一古老(错误的)说法的部分原因。如果人们被告知原始不是对象,但是JS实体可以将它们强制为拳击形式,则这些误解将会消失。