标签:
今天遇到个题目是有关js传递的,做对了一般,另一半错了,这在做选择题的时候那就是错了,没分的!所以大家如果基础不扎实的话就很容易出错,而且做题的时候心里没底,模棱两可,
所以还是要实时不断去复习基础知识,这样才能成长更快!
按值传递(call by value)是最常用的求值策略:函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
按引用传递(call by reference)时,函数的形参接收实参的隐式引用,而不再是副本。这意味着函数形参的值如果被修改,实参也会被修改。同时两者指向相同的值。
按值传递由于每次都需要克隆副本,对一些复杂类型,性能较低;按引用传递会使函数调用的追踪更加困难,有时也会引起一些微妙的BUG。
JS的基本类型,是按值传递的,如下代码可以证明:
1 var a = 1; 2 function foo(x) { 3 x = 2; 4 } 5 foo(a); 6 console.log(a); // 仍为1, 未受x = 2赋值所影响
而对于引用类型来看如下代码:
1 var obj = {x : 1}; 2 function foo(o) { 3 o.x = 3; 4 } 5 foo(obj); 6 console.log(obj.x); // 3, 被修改了!
说明o跟obj指向的是同一个对象,所以不是按值传递的,但是这就能证明js中对象是按引用传递的吗??少年们可以看如下这个例子:
1 var foo = {name:‘foo‘}; 2 function test(o){ 3 o = {name:‘bar‘}; 4 } 5 test(foo); 6 console.log(foo.name);
打印foo.name的值确还是‘foo‘,这就说明js中对象的传递也不是不是按引用传递。好凌乱啊...那js中对象究竟是按什么传递呢?
严格的说,JS中的基本类型按值传递,对象类型按共享传递的(call by sharing,也叫按对象传递、按对象共享传递)。最早由Barbara Liskov. 在1974年的GLU语言中提出。该求值策略被用于Python、Java、Ruby、JS等多种语言。
该策略的重点是:调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)。 它和按引用传递的不同在于:在共享传递中对函数形参的赋值,不会影响实参的值。实质大家可以这么理解:
在调用函数传递引用类型的参数时,传递是是对象引用的副本,但是这个对象引用的副本跟原对象引用指向的是同一个地方(也就是该对象在内存中存放的地址),大家要认真理解这句话!!!!
大家看如下这个例子就印证了按共享传递的观点
1 var foo = {name:‘foo‘}; 2 function test(o){ 3 o.name=‘test‘; 4 o={name:‘bar‘} 5 } 6 test(foo); 7 console.log(foo); 8 //打印结果为: 9 Object {name: "test"}
从上面结果可以得出第一:对象不是按值传递的,如果是按值传递的话打印出来的foo的name属性的值不会为test,因为按值传递的话传递的是对象的一个副本,对副本的修改不会影响元对象,所以可以证明对象不是按值传递的!
也可以证明第二:js中对象也不是完全按引用传递的,如果是按引用传递的话在执行o={name:‘bar‘}这行代码的时候,foo打印的结果应该是Obeject {name:‘bar‘}了,而结果确是Object {name:‘test‘},所以综上两点js引
用类型在作为参数传递时是按共享传递的,即传递是是原对象引用的一个副本,但是这个副本跟原对象的引用指向的都是内存中的对象!
以前学习中知道对于js中基础类型是按值传递的,引用类型是按引用传递,而没有完全理解透彻js中参数传递的方式,所以对js基础知识的理解是非常重要的,一定要掌握牢固,理解透彻,否则浅尝辄止只会让自己是个半桶水,
而成不了一个优秀的前端工程师!
标签:
原文地址:http://www.cnblogs.com/QingChengFE/p/4543608.html