【译】JavaScript原始值的秘密生命 【The Secret Life of JavaScript Primitives】

简介: 【译】JavaScript原始值的秘密生命 【The Secret Life of JavaScript Primitives】

基本原则

对象是属性的聚合。属性可以引用对象或原始数据。基本类型是值,它们没有属性。

在JavaScript中有7种基本类型:undefined、null、boolean、string,number,bigint,symbol。其他一切都是一个对象。基本类型布尔、字符串和数字可以被它们的对应对象包装。这些对象分别是布尔、String和Number构造函数的实例。

typeof true; //"boolean"
typeof Boolean(true); //"boolean"
typeof new Boolean(true); //"object"
typeof (new Boolean(true)).valueOf(); //"boolean"
typeof "abc"; //"string"
typeof String("abc"); //"string"
typeof new String("abc"); //"object"
typeof (new String("abc")).valueOf(); //"string"
typeof 123; //"number"
typeof Number(123); //"number"
typeof new Number(123); //"object"
typeof (new Number(123)).valueOf(); //"number"
复制代码


如果原始类型没有属性,为什么"abc".length会返回一个值?

因为JavaScript很容易在原语和对象之间强制转换。在这种情况下,为了访问属性长度,字符串值被强制转换为字符串对象。字符串对象只被使用了一小会儿,之后它就被献给了垃圾收集之神。

String.prototype.returnMe = function () {
  return this;
};
var a = "abc";
var b = a.returnMe();
a; //"abc"
typeof a; //"string" (still a primitive)
b; //"abc"
typeof b; //"object"
复制代码


正如许多善意的科学调查一样,只要b还在,我们就会干扰事物的自然发展,防止物体被当作垃圾收集。海森堡活得很好😉


(注意,在严格模式下,难以捉摸的生物会逃走-谢谢@DmitrySoshnikov)


下面是一个更环保的例子,它在不干扰垃圾收集的情况下验证对象类型:


Number.prototype.toString = function() {
  return typeof this;
}
(123).toString(); //"object"
复制代码


通过这种方式,原始类型可以访问由各自的对象构造函数定义的所有属性(包括方法)。


这些对象也可以被强制赋值?

是的。主要是。这种类型的对象仅仅是包装器,它们的值是它们包装的原语,它们通常会根据需要强制转换为这个值。


//object coerced to primitive
var Twelve = new Number(12);
var fifteen = Twelve + 3;
fifteen; //15
typeof fifteen; //"number" (primitive)
typeof Twelve; //"object"; (still object)
//another object coerced to primitive
new String("hippo") + "potamus"; //"hippopotamus"
//object not coerced (because 'typeof' operator can work with objects)
typeof new String("hippo") + "potamus"; //"objectpotamus"
复制代码


可悲的是,布尔对象不那么容易强制。更糟糕的是,除非布尔值为空或未定义,否则布尔对象的计算结果为true。试试这个:

if (new Boolean(false)) {
  alert("true???");
}
复制代码


通常你必须显式地询问布尔对象的值。以下可能有助于确定值是否为" false " ....的" true "

var a = "";
new Boolean(a).valueOf(); //false
复制代码


但实际上,这样做更容易。

var a = Boolean("");
a; //false
复制代码


甚至这样

var a = "";
!!a; //false
复制代码


强制是否允许我给原始类型赋值?


如果JavaScript检测到试图将属性赋给一个原语,它确实会强制将原语赋给一个对象。但是,与前面的示例一样,这个新对象没有引用,将立即成为垃圾收集的素材。


下面是同一个示例的伪代码表示,以说明实际发生的情况

var primitive = "september";
primitive.vowels = 3;
//new object created to set property 
(new String("september")).vowels = 3;
primitive.vowels;
//another new object created to retrieve property 
(new String("september")).vowels; //undefined
复制代码


哦,正如你所看到的,它不仅没用,而且相当浪费。


包装对象

事实证明,赋值属性的能力是对象相对于原始对象的唯一优势,但在实践中,即使这是一个值得怀疑的品质。字符串、布尔值和数字具有特定的、定义良好的目的,将它们重新定义为国家持有者很可能会使人们感到困惑。此外,由于原语是不可变的,你不能通过调整对象包装器的属性来修改它们:

var me = new String("Angus");
me.length = 2; //(error in strict mode)
me.length; //5 (not 2 - thanks @joseanpg)
me.valueOf(); "Angus"
复制代码


补充

var me = new String("Angus");
me.length = 2; //(error in strict mode)
const d = Object.getOwnPropertyDescriptor(me, 'length');  
// Object { value: 5, writable: false, enumerable: false, configurable: false }
console.log(d);
复制代码


因为length属性的writablefalse 所以长度不会被赋值而改变。


尽管如此,我确实认为,良好地理解原语以及当您与它们交互时发生了什么,是深入了解该语言的重要一步。我希望这对你有所帮助。



目录
相关文章
|
存储 JavaScript 前端开发
JavaScript中的原始值与引用值
原始值与引用值 在JavaScript中包含两种不同类型的数据:原始值和引用值 原始值 :是指不包含任何引用的值(简单值),比如数字、字符串、布尔值、null和undefined。 引用值 :是指包含了一个引用的值,比如对象、数组、函数和方法。
|
JavaScript 前端开发 PHP
现代 JavaScript 原始数据类型转换你学会了吗?
现代 JavaScript 原始数据类型转换你学会了吗?
105 0
现代 JavaScript 原始数据类型转换你学会了吗?
|
存储 JavaScript 前端开发
在 JavaScript 中,我们能为原始类型添加一个属性或方法吗?
在 JavaScript 中,我们能为原始类型添加一个属性或方法吗?
200 0
|
JavaScript 前端开发 Web App开发
JavaScript 原始数据类型转换
Js基础数据类型有7种: 原始数据类型(6种) number (数值) string (字符串) boolean (布尔) null (空对象, typeof 检测为object) undefine(未定义) symbol (符号类型) ...
941 0
|
前端开发 JavaScript
《JavaScript启示录》——1.11 原始值(String、Number、Boolean)在被用做对象时就像对象
原始值被当作构造函数创建的一个对象来使用时,JavaScript会将其转换为一个对象,以便可以使用对象的特性(如方法),而后抛弃对象性质,并将它变回到原始值。下面的代码采用了原始值,并展示了将值作为对象使用时会发生什么事情。
1211 0
|
存储 JavaScript 前端开发
《JavaScript启示录》——1.10 原始值比较采用值比较
可以通过比较原始值来确定其值在字面上是否相同。从逻辑上讲,如果将一个包含数值10的变量与另一个包含数值10的变量进行比较,JavaScript将会认为它们是相等的,因为10与10是相同的(即10===10)。
1462 0
|
存储 JavaScript 前端开发
《JavaScript启示录》——1.9 如何存储和复制原始值
这里的重点是,原始值是作为不可细化的值进行存储和操作的。引用它们会转移其值。在上面的示例中,我们复制或者克隆了myString值并存储到myStringCopy变量中。当更新myString值时,myStringCopy值仍是旧myString值的副本。
1302 0
|
JavaScript 前端开发
《JavaScript启示录》——1.8 null、undefined、"string"、10、true和false等原始值不是对象
null和undefined都是非常简单的值,它们不需要构造函数,也没有使用new操作符来将自己创建为JavaScript值。欲使用null或undefined,只需将它们看做操作符来使用即可。从技术上来讲,从构造函数返回的字符、数字、布尔值并不是对象。
1665 0
|
JavaScript 前端开发
《JavaScript启示录》——1.7 原始值(或简单值)
了解String()、Number()和Boolean()构造函数是两种目的的构造函数,分别是用于创建字面量/原始值以及复杂值的,这是非常重要的。这些构造函数并不总是返回对象,相反,在不使用new操作符的情况下,它返回实际复杂对象值的原始表示。
1342 0