T.J*_*der 8

除非在极端情况下s是字符串对象而不是字符串原语

const s = new String("");
console.log(s.length === 0); // true
console.log(s === "");       // false
Run Code Online (Sandbox Code Playgroud)

s === ""不起作用,因为===不进行任何类型转换,因此对象永远不会===转换为原始类型。

JavaScript 有点不寻常,因为它具有与其原始类型等效的对象。您几乎总是在处理字符串原语而不是字符串对象,但字符串对象确实存在并且这种区别可能是有效的。与过去相比,现在要知道的事情要少得多。回到 ES5 的严格模式之前,如果你扩展了String.prototype一个isEmpty方法(例如),你的length === 0检查会起作用但=== ""不会:

// Very old loose-mode pre-ES5 code
String.prototype.wrongIsEmpty = function() {
    return this === ""; // WRONG
};
String.prototype.rightIsEmpty = function() {
    return this.length === 0; // Right
};

console.log("".wrongIsEmpty()); // false
console.log("".rightIsEmpty()); // true
Run Code Online (Sandbox Code Playgroud)

问题的原因是在 ES5 的严格模式之前,this在函数中始终是一个对象,而不是原始对象,因此这些方法将字符串对象视为this.

在为 ES5 及更高版本编写的代码中,您将在严格模式下编写,使用哪种检查并不重要,因为在严格模式下,this不必是对象,因此this方法看到的是原始字符串:

"use strict";

Object.defineProperty(String.prototype, "isEmpty1", {
    value: function() {
        return this === ""; // This is fine
    },
    writable: true,
    configurable: true
});
Object.defineProperty(String.prototype, "isEmpty2", {
    value: function() {
        return this.length === 0; // This is fine
    },
    writable: true,
    configurable: true
});

console.log("".isEmpty1()); // true
console.log("".isEmpty2()); // true
Run Code Online (Sandbox Code Playgroud)

(这也使用defineProperty,但严格模式对 的值很重要this。)


创建字符串对象非常罕见,而且几乎从来都不是正确的做法。