2016-06-26

关于JavaScript 函数传参

周五晚上下班回家的路上,突然想到了 CommonJS 规范、Node.js 模块化等等各种东西,然后就想到了熟悉的 module.exports

大约很久之前看 seajs文档,文档强调,exports = {/**/} 这种写法是错误的!当时还是小白中的小白,只能一脸懵逼,为嘛不能啊?完全无法理解。

请看截图:

clipboard.png

有没有看到最后的提示?可惜那时候的小白文蔺完全不知道这是什么鬼——更可能的是那会儿就没关注到这一块儿,毕竟新人,心浮气躁,就想五分钟学会 seajs 模块化开发。

后来摸爬滚打,js 知识相对扎实之后(鸣谢厚厚的红宝书《 JavaScript 高级程序设计》,前后读了三遍),我还是好歹懂了,但未能举一反三。

昨天晚上,再次冒出这个问题,还是了然的。

子曰: 学而不思则罔,思而不学则殆。

很显然,exportsdefine(function(require, exports) {})中就是个局部变量,它对应的值是个对象,是 module.exports 的一个引用。

然后呢,一句exports = {/**/}就把这个局部变量指向另外一个值了。这是局部变量啊喂。卒。

很多新人看了一些博客或者书之后,脑子里也打结了,求值策略按值传递按引用传递,这些似是而非的概念最后都把人给整糊涂了。

刚刚刷SF,读到一篇文章,《JS中的值是按值传递,还是按引用传递呢?》,和我思考的有点类似。

然后搜索了下 “求值策略”,找到汤姆大叔一篇文章,上文与大叔的这篇文章还挺类似的,但大叔的可能显得更深入一点。

下面是引用:

准确的说,JS中的基本类型按值传递,对象类型按共享传递的(call by sharing,也叫按对象传递、按对象共享传递)。最早由Barbara Liskov. 在1974年的GLU语言中提出。该求值策略被用于Python、Java、Ruby、JS等多种语言。

该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。

从科学的角度来说,对于概念什么的,可能还是挺有必要的。从实用角度来说,只要能正确理解,可能用自己的一套语言来描述也是可以的。