栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

原文链接:The Secret Life of JavaScript Primitives

您可能不知道,但在JavaScript中,每当您与字符串、数字或布尔原语交互时,您就进入了一个隐藏的对象阴影和强制的世界。

基本原则

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

在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属性的writable是false 所以长度不会被赋值而改变。

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

本文由 mdnice 多平台发布

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1014577.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号