Javascript基础系列之闭包

前言

本文翻译自evaluation-strategy

按值传递

参数的值是调用者(caller)传递的对象值的拷贝,函数内部改变参数的值不会影响到函数外部的对象。一般来说,通过重新分配内存(这里不关注重新分配内存是如何实现的 -- 可以是堆栈或动态内存分配的方式),将外部对象的值拷贝到新分配的内存,并用于函数内部的计算

但是,如果参数不是原始值,而是一个负复杂的对象,将带来很大的性能问题,C++就有这个问题,将结构作为值传进函数的时候 —— 就是完整的拷贝

按引用传递

按引用传递接收的不是值的拷贝,而是对象的隐式引用,也就是该对象在外部的直接引用地址。函数内部对参数的任何改变都是影响该对象在函数外部的值,因为两者引用的是同一个对象,也就是说:这时候参数就相当于外部对象的一个别名

按共享传递

该策略的要点是:函数接收的是对象引用的拷贝,该引用拷贝和形参以及其值相关联

这里出现的引用,我们不能称之为“按引用传递”,因为函数接收的参数不是直接的对象别名,而是该引用地址的拷贝

最重要的区别就是:函数内部给参数重新赋新值不会影响到外部的对象(按引用传递会改变)。但是,由于形参拥有地址拷贝,和外部指向同一个对象(也就是说,外部对象并不是像按值传递那样完整拷贝),改变参数对象的属性值将会影响到外部的对象。

ECMAScript中就是按共享传递的

ECMAScript中实现

var foo = {x: 10, y: 20};
var bar = foo;

alert(bar === foo); // true

bar.x = 100;
bar.y = 200;

alert([foo.x, foo.y]); // [100, 200]

即两个标识符(名称绑定)绑定到内存中的同一个对象, 共享这个对象:

foo value: addr(0xFF) => {x: 100, y: 200} (address 0xFF) <= bar value: addr(0xFF)

而重新赋值分配,绑定是新的对象标识符(新地址),而不影响已经先前绑定的对象 :

bar = {z: 1, q: 2};

alert([foo.x, foo.y]); // [100, 200] – 没改变
alert([bar.z, bar.q]); // [1, 2] – 但现在引用的是新对象

即现在 foo 和 bar,有不同的值和不同的地址:

foo value: addr(0xFF) => {x: 100, y: 200} (address 0xFF)
bar value: addr(0xFA) => {z: 1, q: 2} (address 0xFA)

再强调一下,这里所说对象的值是地址,而不是对象结构本身,将变量赋值给另外一个变量 —— 是赋值值的引用。因此两个变量引用的是同一个内存地址。下一个赋值却是新地址,是解析与旧对象的地址绑定,然后绑定到新对象的地址上,这就是和按引用传递的最重要区别

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,684评论 8 265
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,160评论 1 32
  • 本次作业为将在下周为全行微信直播培训的演讲稿,权当为本次作业。大家晚上好,我是投行与金融市场部的吴智伟,从去年7月...
    firekeeprunning阅读 357评论 0 0
  • 我有一种能力——搬砖 这听上去确实有点无厘头。我说的“砖”不是起厝的砖,而用来保护自己的砖,没有人...
    杨美丽RICE阅读 220评论 2 1
  • 材料: 冰淇淋粉 牛奶 步骤1 将冰淇淋粉和牛奶按照3:8的比例准备好,把牛奶匀速倒入冰淇淋粉中并不停搅拌至均匀,...
    蘑菇公举阅读 709评论 0 10