广告
返回顶部
首页 > 资讯 > 前端开发 > JavaScript >详细讨论JavaScript中的求值策略
  • 743
分享到

详细讨论JavaScript中的求值策略

JavaScript求值策略Javascript参数 2022-11-12 02:11:54 743人浏览 泡泡鱼
摘要

目录一栗以蔽之参数传递按值传递按共享传递总结延伸 - 惰性求值最近在研究 lambda演算 中的 η-变换 在javascript中的应用,偶然在 stackoverflow 上看到

最近在研究 lambda演算 中的 η-变换 在javascript中的应用,偶然在 stackoverflow 上看到一个比较有意思的问题。关于JavaScript的求值策略,问js中函数的参数传递是按值传递还是按引用传递?回答很经典。

一栗以蔽之


function changeStuff(a, b, c) {
  a = a * 10;
  b.item = "changed";
  c = {item: "changed"};
}

var num = 10;
var obj1 = {item: "unchanged"};
var obj2 = {item: "unchanged"};

changeStuff(num, obj1, obj2);

console.log(num);         // 10
console.log(obj1.item);   // changed
console.log(obj2.item);   // unchanged

如果说js中函数的参数传递是按值传递,那么在函数changeStuff内部改变b.item的值将不会影响外部的obj1对象的值。

如果说JS中函数的参数传递是按引入传递,那函数changeStuff内部所做的改变将会影响到函数外部所有的变量定义,num将会变成100、obj2.item将会变成changed。很显然实际不是这样子的。

所以不能说JS中函数的参数传递严格按值传递或按引入传递。总的来说函数的参数都是按值传递的。JS中还采用一种参数传递策略,叫按共享传递。这要取决于参数的类型。

如果参数是基本类型,那么是按值传递的;

如果参数是引用类型,那么是按共享传递的。

参数传递

ECMAScript 中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样。基本类型值的传递如同基本类型变量的复制一样,而引用类型值的传递,则如同引用类型变量的复制一样。-- 《JavaScript高级程序设计》

红宝书上讲所有函数的参数都是按值传递的,到底是不是呢?让我们分析下上面的栗子:

按值传递

JavaScript中基本类型作为参数的策略为按值传递(call by value):


function foo(a) {
  a = a * 10;
}

var num = 10;

foo(num);

console.log(num); // 10 没有变化

这里看到函数内部参数的改变并没有影响到外部变量。按值传递没错。

按共享传递

JavaScript中对象作为参数传递的策略为按共享传递(call by sharing):

修改参数的属性将会影响到外部对象

重新赋值将不会影响到外部对象

按上面栗子函数内部修改了参数b的属性item,会影响到函数外部对象,因而obj1的属性item也变了。


function bar(b) {
  b.item = "changed";
  console.log(b === obj1) // true
}

var obj1 = {item: "unchanged"};

bar(obj1);

console.log(obj1.item);   // changed 修改参数的属性将会影响到外部对象

从b === obj1打印结果为true可以看出,函数内部修改了参数的属性并没有影响到参数的引用。b和obj1共享一个对象地址,所以修改参数的属性将会影响到外部对象。

而将参数c重新赋值一个新对象,将不会影响到外部对象。


function baz(c) {
  c = {item: "changed"};
  console.log(c === obj2) // false
}

var obj2 = {item: "unchanged"};

baz(obj2);

console.log(obj2.item);   // unchanged 重新赋值将不会影响到外部对象

将参数c重新赋值一个新对象,那么c就绑定到了一个新的对象地址,c === obj2打印结果为false,判断他们不再共享同一个对象地址。它们各自有独立的对象地址。所以重新赋值将不会影响到外部对象。

总结

可以说按共享传递是按值传递的特例,传递的是引用地址的拷贝。所以红宝书上说的也没错。

可以把 ECMAScript 函数的参数想象成局部变量。-- 《JavaScript高级程序设计》

延伸 - 惰性求值

前面了解到了所有函数的参数都是按值传递的。JavaScript 中参数是必须先求值再作为实参传入函数的。但是在es6中有一个特例。

参数默认值不是传值的,而是每次都重新计算默认值表达式的值。也就是说,参数默认值是惰性求值的。 -- 《ECMAScript 6 入门


let x = 99;
function foo(p = x + 1) {
  console.log(p);
}

foo() // 100

x = 100;
foo() // 101

上面代码中,参数p的默认值是x + 1。这时,每次调用函数foo,都会重新计算x + 1,而不是默认p等于 100

以上就是详细讨论JavaScript中的求值策略的详细内容,更多关于JavaScript求值策略的资料请关注编程网其它相关文章!

--结束END--

本文标题: 详细讨论JavaScript中的求值策略

本文链接: https://www.lsjlt.com/news/124733.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作