资讯专栏INFORMATION COLUMN

JS淬炼: Primitive vs. Object

Hancock_Xu / 1029人阅读

摘要:值传递引用传递是值传递,是引用传递。但这影响会根据父类是属于还是而有微妙差别。我们设想有一个父类,和两个继承了他的子类和。这时,子类修改该不会影响到父类本身,更不会传递到其他子类上。

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通过对引用指向的修改来实现同一个变量指向不同的数据类型。

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?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/80961.html

相关文章

  • JS淬炼: Array进阶

    摘要:的这种实现方式导致了一些尴尬问题,比如删除元素元素遍历。后面的参数被忽略掉了,表示并没有要插入的元素。其实,的本质是跟踪中的,并始终保持值是。这时候,虽然不大可能,可能会在中间某个中被用户重新定义。但是在上进行这种操作是很糟糕的。 在Javascript中,array是一个类数组的object。顾名思义,它能够在一个变量上存储多个值。 数组是值的有序集合。每个值叫做一个元素,而每个元素...

    jimhs 评论0 收藏0
  • 關於 Javascript {} + {}

    摘要:於是其他的東西相加的時候將會被轉型成數字或者字串。整個過程即先依據轉換為原始型別,這裡要注意並不是最終結果,再來依據需要看是否要再將原生型別轉成數字或字串。這個結果等於只作的算。 這篇文章源自 What is {} + {} in JavaScript? 其實早在 2012 年就問世了。時至 2016 年末純粹是在聊天時重提這個問題,但由於年紀大了記憶力不佳,竟然記錯了,所以才會有這一...

    charles_paul 评论0 收藏0
  • JS淬炼: Syntax Parser

    摘要:语法分析利用词法分析的结果建立上下文关系语法树。一般情况下,我们不会直接和语法树打交道,但会在进行代码压缩语法高亮重编译关键字匹配和作用域判断时间接涉及到。传统的引擎直接根据语法树的的结果进行解释执行,导致效率比较为低下。 一门语言的执行,大致经历下面这些过程:词法分析 -- 语法分析 -- 语义分析 -- 中间代码生成 -- 优化代码 -- 代码生成。 在Javascript中,Sy...

    wuaiqiu 评论0 收藏0
  • Learning Notes - Understanding the Weird Parts of

    摘要:标签前端作者更多文章个人网站 Learning Notes - Understanding the Weird Parts of JavaScript 标签 : 前端 JavaScript [TOC] The learning notes of the MOOC JavaScript: Understanding the Weird Parts on Udemy,including...

    inapt 评论0 收藏0
  • JS中将变量转为字符串

    摘要:将与空字符串相加,即可将其转换为字符串。这两者是非常不同的事实上,将作为构造函数使用并不常见,因此仅使用它来转换字符串就好了。这就意味着两者的计算过程是这样的返回值,然后使用转换为字符串。 译者按: 语言的细枝末节了解一下就可以了,不需要太较真,不过如果一点也不知道的话,那就不太妙了。 原文: Converting a value to string in JavaScript 译...

    Alex 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<