<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引用类型“赋值”的工作方式。

首先是

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

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

这一步很好理解,接着继续看下一行非常重要的代码:

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

我们知道js的赋值运算顺序永远都是从右往左的,不过由于“.”是优先级最高的运算符,所以这行代码先“计算”了a.x。

这时候发生了这个事情——a指向的对象{n:1}新增了属性x(虽然这个x是undefined的):

从图上可以看到,由于b跟a一样是指向对象A的,要表示A的x属性除了用a.x,自然也可以使用b.x来表示了。

接着,依循“从右往左”的赋值运算顺序先执行 a={n:2} ,这时候,a指向的对象发生了改变,变成了新对象{n:2}(我们称为对象B):

接着继续执行 a.x=a,很多人会认为这里是“对象B也新增了一个属性x,并指向对象B自己”

但实际上并非如此,由于一开始js已经先计算了a.x,便已经解析了这个a.x是对象A的x,所以在同一条公式的情况下再回来给a.x赋值,也不会说重新解析这个a.x为对象B的x。

所以 a.x=a 应理解为对象A的属性x指向了对象B:

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

而在console.log(b.x)的时候,由于b.x表示对象A的x属性,该属性是指向对象B,自然也输出了[object Object]了,注意这里的[object Object]可不是2个对象的意思,对象的字符串形式,是隐式调用了Object对象的toString()方法,形式是:"[object Object]"。所以[object Object]表示的就只是一个对象罢了:)

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

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

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

    简单粗暴地理解js原型链–js面向对象编程 作者:茄果 链接:http://www.cnblogs.com/qieguo/archive/2016/05/03/5451626.html 原型链理解起来 ...

  2. 一个简单例子:贫血模型or领域模型

    转:一个简单例子:贫血模型or领域模型 贫血模型 我们首先用贫血模型来实现.所谓贫血模型就是模型对象之间存在完整的关联(可能存在多余的关联),但是对象除了get和set方外外几乎就没有其它的方法,整个 ...

  3. javascript编写一个简单的编译器(理解抽象语法树AST)

    javascript编写一个简单的编译器(理解抽象语法树AST) 编译器 是一种接收一段代码,然后把它转成一些其他一种机制.我们现在来做一个在一张纸上画出一条线,那么我们画出一条线需要定义的条件如下: ...

  4. (转)Java中使用正则表达式的一个简单例子及常用正则分享

    转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...

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

    多线程的一个简单例子: #include <stdio.h> #include <stdlib.h> #include <string.h> #include &l ...

  6. quartz---的一个简单例子

    quartz---的一个简单例子 首先建立一个maven项目.jar工程即可.(提示:我前面有如何建立一个maven工程的总结以及maven环境的配置.) 1.建立好后点击到app中运行,--> ...

  7. 用socket.io实现websocket的一个简单例子

    socket.io 是基于 webSocket 构建的跨浏览器的实时应用. 逛博客发现几个比较好的 一.用socket.io实现websocket的一个简单例子 http://biyeah.iteye ...

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

    最近工作项目需要用到js排列组合,于是就写了一个简单的demo. 前几天在网上找到一个写全排列A(n,n)的code感觉还可以,于是贴出来了, 排列的实现方式: 全排列主要用到的是递归和数组的插入 比 ...

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

    词法分析的理论知识不少,包括了正规式.正规文法.它们之间的转换以及确定的有穷自动机和不确定的有穷自动机等等... 要自己写一个词法分析器也不会很难,只要给出了最简的有穷自动机,就能很方便实现了,用if ...

随机推荐

  1. Linux下的虚拟Bridge实现

    http://www.cnblogs.com/zmkeil/archive/2013/04/21/3034733.html Linux下的Bridge也是一种虚拟设备,这多少和vlan有点相似,它依赖 ...

  2. oracle数据库升级记(记一次10.2.0.3版本升级到11.2.0.1版本的过程)

    操作系统:windows xp 已有数据库版本:10.2.0.3 升级目标版本:11.2.0.1 步骤大纲: 在源操作系统(安装有10.2.0.3数据库的操作系统)上安装11.2.0.1数据库软件,然 ...

  3. 新手看Mockplus

    如今是一个快节奏的社会,每一天都会有无数的软件发布,每一款软件的制作过程不可避免的需要使用原型设计工具.而Mockplus就是一款原型设计软件,可以用于移动端,PC端以及WEB的原型设计.它也符合如今 ...

  4. mvc AddImplicitRequiredAttributeForValueTypes

    1.AddImplicitRequiredAttributeForValueTypes (为值类型添加隐式必填验证),默认值 为true.刚在mvc view(html)中会为model的值类型属性( ...

  5. REST有状态与无状态的理解

    1. 什么是REST? REST(REpresentation State Transfer)表述性状态传递,是一种软件架构风格,是一种针对网络应用的设计和开发方式,可以降低开发的复杂性,提高系统的可 ...

  6. Java多线程基本概念

    基本概念 线程与任务的概念不一样. 任务:通常是一些抽象的且离散的工作单元,比如在Web请求中,针对用户的请求需要返回相应的页面是一个任务,在Java中实现Runnable接口的类也是一个任务. 线程 ...

  7. Jquery给input[type=radio] 控件赋值

    setobject: function (data, scope, win) { //data jsoon数据, scope,一般为form的id,win 窗口对象,如果在当前window win=n ...

  8. 给angularJs的service建模

    先回顾一下我们遇到的问题: 通过一个dialogService创建对话框,并将该service的参数数据通过resolve的方式传递给对话框的controller. controller解析数据后放置 ...

  9. BZOJ2933: [Poi1999]地图

    Description   一个人口统计办公室要绘制一张地图.由于技术的原因只能使用少量的颜色.两个有相同或相近人口的区域在地图应用相同的颜色.例如一种颜色k,则A(k) 是相应的数,则有: 在用颜色 ...

  10. VIM的一些操作小技巧

    vim的设计理念是:组合. 命令的组合,模式的组合,     普通模式 左: h 上:k 下:j 右 : l   i : 当前光标处插入 I: 到光标所在行的行首进入插入模式 a: 在当前光标的后一位 ...