You may not know it but, in JavaScript, whenever you interact with string, number or boolean primitives you enter a hidden world of object shadows and coercion. So dust off your Sherlock Holmes outfit and read on…
The basics
Objects are aggregations of properties. A property can reference an object or a primitive. Primitives are values, they have no properties.
In JavaScript there are 5 primitive types: undefined
, null
, boolean
, string
and number
. Everything else is an object. The primitive types boolean, string and number can be wrapped by their object counterparts. These objects are instances of the Boolean
, String
and Number
constructors respectively.
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"
.
If primitives have no properties, why does "abc".length
return a value?
Because JavaScript will readily coerce between primitives and objects. In this case the string value is coerced to a string object in order to access the property length. The string object is only used for a fraction of second after which it is sacrificed to the Gods of garbage collection – but in the spirit of the TV discovery shows, we will trap the elusive creature and preserve it for further analysis…
1
2
3
4
5
6
7
8
9
10
11
|
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"
|
…and as with many well meaning scientific investigations we have now interfered with the natural progression of things and prevented the object from being garbage collected so long as b
is around. Heisenberg is alive and well
(Note that in strict mode, the elusive creature gets away – thanks @DmitrySoshnikov)
Here’s a more environmentally responsible example that verifies the object type without interfering with garbage collection:
1
2
3
4
5
|
Number.prototype.toString = function () {
return typeof this ;
} (123).toString(); //"object"
|
.
By this means primitives have access to all the properties (including methods) defined by their respective object constructors.
And these objects can also be coerced to values?
Yes. Mostly. Objects of this type are merely wrappers, their value is the primitive they wrap and they will generally coerce down to this value as required. For full details see this article.
1
2
3
4
5
6
7
8
9
10
11
12
|
//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"
|
Sadly boolean objects do not coerce so easily. And, to add insult to injury, a boolean object evaluates to true unless its value is null or undefined. Try this:
1
2
3
|
if ( new Boolean( false )) {
alert( "true???" );
} |
Usually you have to explicitly ask boolean objects for their value. The following might be useful for determining whether the value is “truthy” of “falsey”….
1
2
|
var a = "" ;
new Boolean(a).valueOf(); //false
|
…but in practice its easier to do this…
1
2
|
var a = Boolean( "" );
a; //false
|
..or even this…
1
2
|
var a = "" ;
!!a; //false
|
.
Does coercion allow me to assign values to primitives?
No.
1
2
3
4
|
var primitive = "september" ;
primitive.vowels = 3; primitive.vowels; //undefined;
|
If JavaScript detects an attempt to assign a property to a primitive it will indeed coerce the primitive to an object. But, as with the previous examples, this new object has no references and will immediately become fodder for garbage collection.
Here’s a pseudo-code representation of the same example to illustrate what really happens
1
2
3
4
5
6
7
8
|
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
|
So as you can see, its not only useless but pretty wasteful.
Wrap up
It turns out that the ability to assign properties is just about the only advantage of objects over their primitive counterparts, but in practice even this is a dubious quality. Strings, booleans and numbers have specific and well defined purposes and redefining them as state holders is likely just going to confuse people. Moreover, since primitives are immutable you cannot modify them by tweaking the properties of the object wrapper:
1
2
3
4
|
var me = new String( "Angus" );
me.length = 2; //(error in strict mode)
me.length; //5 (not 2 - thanks @joseanpg)
me.valueOf(); "Angus"
|
Nevertheless, I do think that a good understanding of primitives and what happens under the covers when you interact with them is an important step towards a deeper knowledge of the language. I hope this helped.
相关推荐
.NET Composition Primitives是.NET框架中用于构建复杂应用程序和系统的核心组件。这些抽象概念和机制使得开发者能够以模块化、可扩展的方式组装应用,允许不同组件之间进行协作和交互。本文将深入探讨.NET ...
You'll learn all about Closure's Library, Compiler, Templates, testing framework, and Inspector -- including how to minify JavaScript code with the Compiler, and why the combination of the Compiler ...
通常,你可以选择“Code samples for the Intel® Integrated Performance Primitives (Intel® IPP)”获取示例代码,或者选择“Free non-commercial version of the Intel® Integrated Performance Primitives ...
By placing a collection of primitives in the correct location and of the correct size we can create a represent complex structural objects. To create complex objects, primitives can be used as ...
在这个名为"owski-primitives"的项目中,作者提供了一组经过柯里化(Currying)处理的原始函数,以帮助开发者更高效地编写JavaScript代码,特别是在构建复杂的函数组合时。 柯里化是将接受多个参数的函数转化为接受...
Chapter 8 describes the lighting of geometric primitives. The lighting model is introduced and the supported shading algorithms and light types are de- scribed. Chapter 9 covers programmable vertex ...
It gives the implementation details of one set of primitives, usually the most popular set. Once readers understand how primitives can be implemented on conventional hardware, they can then easily ...
If you’re a scientist who programs with Python, this practical guide not only teaches you the fundamental parts of SciPy and libraries related to it, but also gives you a taste for beautiful, easy-...
Some of the things that I'm doing here are similar to the utilities found on the sysinternals Web site. NtSysInfo Syntax NtSysInfo enables you to explore the Windows NT internals and enumerate the ...
Elegant SciPy: The Art of Scientific Python by Juan Nunez-Iglesias English | 11 Aug. 2017 | ISBN: 1491922877 | ASIN: B...Process large datasets with Python data streaming primitives and the Toolz library
You will learn the key differences between classical polymorphism and generic programming, the foundation of the STL. You will also learn how to use the various algorithms and containers in the STL ...
使用低级原语(Low-Level Primitives)进行设计,是实现这一目标的关键手段之一。本知识点将深入探讨如何在Altera FPGA芯片上利用其内部资源,合理分配并设计高效电路。 首先,对于Altera FPGA芯片来说,了解其内部...
Someone who’s intimately familiar with JavaScript may find that many of these subjects are already well understood, and others who know data visualization may well feel the same way about several of ...
group, such as their message primitives, and applies them in the context of proof. Industrial-grade protocols such as SSL/TLS, Kerberos and even the huge SET protocol suite [37] can then be tackled. ...
npm install sync-primitives 原料药 信号 构造函数 number [value = 1] 获得 Object [选择] boolean [blocking = true] boolean [超时= -1] return : Promise. 释放 锁 function fn Object [选择] boolean ...