美文网首页程序员
JS淬炼: Primitive vs. Object

JS淬炼: Primitive vs. Object

作者: Hackjutsu | 来源:发表于2016-11-20 03:29 被阅读47次

Javascript有两种基本数据类型,Primitive和Object。Object是properties的聚合,其property可以是Object也可以是Primitive。Primitive只有value, 没有properties。Javascript有五种Primitive:

  • string
  • number
  • boolean
  • null
  • undefined

除了nullundefined,其余Primitive都有对应的Object封装,如Object String对应string

Stack vs Heap

Javascript是一门动态语言,同一个变量在不同时候可能被赋予不同数据类型,比如前面是number而后面变成Object。所以Javascript变量值所占用的内存空间应该是可以动态变化的。

var a = 10;
a = {};

实际上,不管是Primitive还是Object,这些Javascript变量的值都存储在可以动态分配空间的heap上。而它在stack上保存的则是一个固定size的包含该值所在heap位置信息的引用(类似pointer)。JS engine通过对引用指向的修改来实现同一个变量指向不同的数据类型。

Javascript memory model

It's wrong to state that primitives are allocated from the stack and only objects are allocated from the heap. This is the biggest difference between C and JavaScript.

最新的JS engine做了很多优化,使得内存分配更为高效但也更为复杂,具体可参考该StackOverflow回答

值传递 vs 引用传递

Primitive是值传递(passed by value),Object是引用传递(passed by reference)

上面说到,Javascript变量在stack保存的是地址引用,为什么又说Primitive是值传递呢?Javascript中所有Primitive都是immutable的。在传递Primitive时,JS engine在heap上复制一个值相同的Primitive,然后把新变量的引用传递出去,这就是所谓JS中的值传递。对于Object,JS engine并不会复制一个新的Object,而是直接传递它的地址引用(与C++/Java中的引用传递类似)。

该引用能识别其指向的变量是Primitive还是Object,所以它不是一个简单的pointer,而是包含所指向变量类型信息的“智能引用”。

对Prototype影响

在Javascript中,子类修改父类的property会影响到所有继承该父类的子类。但这影响会根据父类property是属于Primitive还是Object而有微妙差别。我们设想有一个父类father,和两个继承了他的子类son1son2

var father = { 
    primitive: 1,
    object: {
        fruit: "APPLE" 
    }
};
var son1 = Object.create(father);
var son2 = Object.create(father);

Primitive Property

如果父类的property是Primitive,该property通过passed by value传递到子类。这时,子类修改该property不会影响到父类本身,更不会传递到其他子类上。

console.log("father's primitive is " + father.primitive);
console.log("son1's primitive is " + son1.primitive);
console.log("son2's primitive is " + son2.primitive);
// father's primitive is 1
// son1's primitive is 1
// son2's primitive is 1

son1.primitive = 2;

console.log("father's primitive is " + father.primitive);
console.log("son1's primitive is " + son1.primitive);
console.log("son2's primitive is " + son2.primitive);
// father's primitive is 1
// son1's primitive is 2
// son2's primitive is 1

Object Property

如果父类的property是Object,该property通过passed by reference传递到子类上。子类修改该property会通过父类传递到所有继承它的子类上。

console.log("father's fruit is " + father.object.fruit);
console.log("son1's fruit is " + son1.object.fruit);
console.log("son2's fruit is " + son2.object.fruit);
// father's fruit is APPLE
// son1's fruit is APPLE
// son2's fruit is APPLE

son1.object.fruit = "GRAPE";

console.log("father's fruit is " + father.object.fruit);
console.log("son1's fruit is " + son1.object.fruit);
console.log("son2's fruit is " + son2.object.fruit);
// father's fruit is GRAPE
// son1's fruit is GRAPE
// son2's fruit is GRAPE

Reference

Primitive value vs Reference value
How variables are allocated memory in Javascript?

相关文章

  • JS淬炼: Primitive vs. Object

    Javascript有两种基本数据类型,Primitive和Object。Object是properties的聚合...

  • JS淬炼: Array入门

    Javascript arrays are used to store multiple values in a ...

  • JS淬炼: Array进阶

    在Javascript中,array是一个类数组的object。顾名思义,它能够在一个变量上存储多个值。 数组是值...

  • JS淬炼: Syntax Parser

    一门语言的执行,大致经历下面这些过程:词法分析 -- 语法分析 -- 语义分析 -- 中间代码生成 -- 优化代码...

  • Object spread(对象展开语法) vs. Object

    Object spread vs. Object.assign:For the most part object ...

  • “人”变为“人才”的第1步是环境淬炼

    目标的实现离不开环境淬炼和自我淬炼,对绝大多数人而言都是先有环境淬炼才有自我淬炼,因为人都有惰性,《华与华正道》中...

  • lodash相关技巧

    变量和方法 类型 js的变量中只用primitive类型和object类型 平时使用的字符串应该是primitiv...

  • GeekBand笔记: C++面向对象高级编程(1)

    面向对象 Object Oritented 基于对象(Object Based) vs. 面向对象(Object ...

  • 淬炼

    我听到秋风在呜咽 我体内的血在下沉 路一直向前,消失在白杨里 那秋日的白杨,是升腾的火焰 火焰让血疼痛 疼痛分娩着...

  • 淬炼

    前几日写了篇《浆水》,里面提到加浆水引子时的温度选择,妈妈的做法是在水温很烫的时候把引子加进去,我自认为温度太高,...

网友评论

    本文标题:JS淬炼: Primitive vs. Object

    本文链接:https://www.haomeiwen.com/subject/rcgepttx.html