从一个简单例子来理解js引用类型指针的工作方式

?





1

2

3

4

5

6

7

<script>

var
a = {n:1}; 

var
b = a;  

a.x = a = {n:2}; 

console.log(a.x);// --> undefined 

console.log(b.x);// --> [object Object] 

</script>

上面的例子看似简单,但结果并不好了解,很容易把人们给想绕了——“a.x不是指向对象a了么?为啥log(a.x)是undefined?”、“b.x不是应该跟a.x是一样的么?为啥log出来居然有2个对象”

当然各位可以先自行理解一下,若能看出其中的原因和工作机理自然就无须继续往下看啦。

下面来分析下这段简单代码的工作步骤,从而进一步理解js引用类型“赋值”的工作方式。

首先看下a.x=a={n:2}这段代码,实际等价于:

a.x=a;

a={n:2}

虽然js中运算赋值顺序应是从左往右,但鉴于运算符“.”的级别是最高的,故先执行了最左边的“a.x=a”,再执行“a={n:2}”。

这一步说明了,我们就从头到尾一步步看下js是怎么执行这段代码的。

首先是

var a = {n:1}; 
var b =
a;

在这里a指向了一个对象{n:1}(我们姑且称它为对象A),b指向了a所指向的对象,也就是说,在这时候a和b都是指向对象A的:

这一步很好理解,接着继续看下一行代码:

a.x = a = {n:2};

也就是上面我们说过的可以拆成两行看的代码:

a.x = a ;   
//当然这样的写法是不提倡的,循环引用,会引起内存泄漏

a = {n:2};

这个时候发生了这样的事情——通过a.x给对象A增加了一个属性x,同时这个属性x是指向对象A自己的;接着由于“a={n:1}”,所以a不再指向原对象A,而是指向新对象{n:2}(我们称为对象B):

这里有个好玩的事情,由于对象A增加了一个属性x,鉴于b是指向对象A的,所以我们也可以通过b.x来表示A对象的这个新属性。

那么这时候结果就显而易见了。当console.log(a.x)的时候,a是指向对象B的,但对象B没有属性x。没关系,当查找一个对象的属性时,JavaScript
会向上遍历原型链,直到找到给定名称的属性为止。但当查找到达原型链的顶部 - 也就是 Object.prototype -
仍然没有找到指定的属性B.prototype.x,自然也就输出undefined;

而在console.log(b.x)的时候,由于b.x表示对象A的x属性,该属性是指向对象A本身。A对象有2个属性n和x,自然也输出了2个Object了。

以上纯粹为个人对js引用类型工作方式的理解,若有不对的地方请指出谢谢 :)

从一个简单例子来理解js引用类型指针的工作方式,布布扣,bubuko.com

时间: 2024-12-14 13:05:44

从一个简单例子来理解js引用类型指针的工作方式的相关文章

简单粗暴地理解js原型链--js面向对象编程

简单粗暴地理解js原型链--js面向对象编程 原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好. 不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么.简单粗暴点看原型链吧,想点与代码无关的事,比如人.妖以及人妖. 1)人是人他妈生的,妖是妖他妈生的.人和妖都是对象实例,而人他妈和妖他妈就是原型.原型也是对象,叫原型对象. 2)人他妈和人他爸啪啪啪能生出一堆人宝宝.妖他妈和妖他爸啪啪啪能生出一堆妖宝宝,啪啪啪就是构造函数,俗

一个简单且丑陋的js切换背景图片基础示例

不多说,直接上代码,非常基础的一个原生js切换元素背景图片范例 <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>原生JS范例</title> <script type="text/javascript"> function changeBg()

C语言多线程的一个简单例子

多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <pthread.h> void * print_a(void *); void * print_b(void *); int main(){ pthread_t t0; pthread_t t1; // 创建线程A if(pthread_creat

生产者与消费者的一个简单例子

生产者 #include<fstream> #include<iostream> #include<Windows.h> using namespace std; int main(void) { ofstream out; const char ch = '*'; long long k = 0; DWORD64 time = GetTickCount64(); while (true) { if (GetTickCount64() - time > 5000)

js 排列 组合 的一个简单例子

最近工作项目需要用到js排列组合,于是就写了一个简单的demo. 前几天在网上找到一个写全排列A(n,n)的code感觉还可以,于是贴出来了, 排列的实现方式: 全排列主要用到的是递归和数组的插入 比如12的全排列,首先把1拿出来放到elementCur,再获取由1组成的数组[2],然后在循环把1插入到0,1的位置后再返回1,2][2,1] 如果是123那么首先获取23的全排列[2,3][3,2],然后在插入1,[1,2,3][2,1,3][2,3,1][1,3,2][3,1,2][3,2,1]

一个简单例子了解使用互斥量线程同步

在刚开始学习学习线程同步时总是认为两个线程或是多个线程共同运行,但是那样是做的. 同步就是协同步调,按预定的先后次序进行运行.如:你说完,我再说. "同"字从字面上容易理解为一起动作. 其实不是,"同"字应是指协同.协助.互相配合. 如进程.线程同步,可理解为进程或线程A和B一块配合,A执行到一定程度时要依靠B的某个结果,于是停下来,示意B运行:B依言执行,再将结果给A:A再继续操作. 所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不返回,同时其它

PyQt安装与一个简单例子

PyQt在Windows+Visual Studio下安装所需文件如下: python-2.7.3.msi (www.python.org/download) sip-4.14.2.zip (www.riverbankcomputing.co.uk/software/sip/download) PyQt-Py2.7-x86-gpl-4.9.6-1.exe(www.riverbankcomputing.co.uk/software/pyqt/download) 安装方法: 首先安装python2.

词法分析程序 LEX和VC6整合使用的一个简单例子

词法分析的理论知识不少,包括了正规式.正规文法.它们之间的转换以及确定的有穷自动机和不确定的有穷自动机等等... 要自己写一个词法分析器也不会很难,只要给出了最简的有穷自动机,就能很方便实现了,用if.switch-case来写一通所谓的状态转换就可以,我近期会写一个简单的词法分析程序来作为例子... 现在已经有人发明了一个叫LEX的工具让你去应用,那我们就省了不少力气,毕竟没到万不得已的时候,我们都没必要重新发明轮子,从另一个角度来说,使用工具是我们人类知识继承的一种方法,也是我们比其他动物优

netsh interface portproxy的一个简单例子

netsh interface portproxy的微软帮助文档地址: https://technet.microsoft.com/zh-cn/library/cc776297(WS.10).aspx#BKMK_1 下面是一个简单的例子: //显示所有 portproxy 参数,包括 v4tov4.v4tov6.v6tov4 和 v6tov6 的端口/地址对. C:\>netsh interface portproxy show all //因为没有配置过它,所以没有东西可以显示. //添加配置