简单情况

var v1 = {}
function func(obj){
  obj = {
    name:'v1'
  }
}
function fund(obj){
  obj.name = 'v1'
}
func(v1)
console.log(v1) // {}
fund(v1)
console.log(v1) // { name: 'v1' }

在执行func(v1)后,v1的地址address01被作为参数传入,并以变量名obj保存。obj ={name:'v1'}之后,obj保存的是新对象的地址address04。而v1保存的地址address01没有变化。其后执行fund(v1)v1的地址address01被作为参数传入,并以变量名obj保存。obj.name = 'v1',修改地址address01中名为name的值。所以通过v1访问地址,显示内容变化。

clipboard.png

复杂情况

function c() {
  var obj = {
    v: 1
  }
  obj.fund = function () {
    obj.v++
  }
  obj.func = function () {
    obj = {
      v: -1
    }
  }
  return obj
}

var c1 = c()
c1.func()
console.log(c1) // { v: 1, fund: [Function], func: [Function] }
c1.fund()
console.log(c1) // { v: 1, fund: [Function], func: [Function] }

首先执行var c1 = c()。运行c()函数c中有个局部变量obj,对其一顿操作后,将这个对象的地址address02返回,通过c1=,赋给c1

clipboard.png

接着执行c1.func()函数func调用的是其外部变量obj,原本变量名obj对应的地址是address02,经过obj={v:-1},用新对象的地址address05代替原来的地址。此时c1指向的地址仍是address02。所以c1.fund()修改的是地址为address05的对象。

clipboard.png

修改代码证明一下

function c() {
  var obj = {
    v: 1
  }
  obj.fund = function () {
    obj.v++
  }
  obj.func = function () {
    obj = {
      v: -1
    }
  }
  obj.getObj = function () {
    return obj
  }
  return obj
}

var c1 = c()
var innerObj1 = c1.getObj()
c1.func()
var innerObj2 = c1.getObj()
console.log(innerObj1 === innerObj2) // false

在没执行c1.func()之前,函数getObj访问的是函数c中的局部变量obj,其地址是address02。在执行c1.func()之后,函数getObj访问的仍是函数c中的局部变量obj,但其地址已经变成address06

clipboard.png

含this的情况

function c() {
  this.obj = {
    v: 1
  };
  this.func = function () {
    this.obj = {
      v: 2
    };
  };
}

var c2 = new c();
var obj1 = c2.obj
c2.func();
console.log(c2.obj.v); // 2
console.log(c2.obj === obj1) // false

clipboard.png

最后一个例子

function setName(obj){
    obj.name="ted"; // 第二步
    obj=new Object(); // 第三步
    obj.name="marry"; // 第四步
}
var obj=new Object(); // 第一步
setName(obj); // 进入第二步
console.log(obj.name); // ted

clipboard.png


nbb3210
436 声望31 粉丝

优雅地使用JavaScript解决问题