JavaScript的赋值是引用or复制,及参数传递

先来看2014年阿里巴巴前端线上笔试题:前端

var a = 1;
var obj = {
    b: 2
};
var fn = function () {};
fn.c = 3;

function test(x, y, z) {
    x = 4;
    y.b = 5;
    z.c = 6;
    return z;
}
test(a, obj, fn);
alert(a + obj.b + fn.c);

答案是12,若是回答得正确,就不必看下去。If not,就跟我一块儿来学习下好啦~面试

(一)基本类型函数

因为学js没多久,对赋值到底是引用仍是复制不是很清楚(若是是引用,那一个值改变会影响另外一个,若是是复制,那各玩各的,互不影响),遇到这类问题每每就很迷糊。花了半天时间参阅了一些资料,整理以下。学习

首先,JavaScript的基本类型有boolean, string, number,还有undefined和null,啊你确定会说干吗又扯最无聊的any book的语法第一章内容,了解这个又怎么样,还真的有用呢。首先得明白的是,只有字面量的boolean,string和number,以及undefined + null(exact undefined null,区分大小写)才是属于基本类型的,new出来的不算。spa

即:code

alert(typeof false);//"boolean"
var b = new Boolean(false);
alert(typeof b);//"object"

一样,new String('aaa')这种都不是基本类型,直接的a = 'aaa',a是基本类型,这就是:字面量的才是基本类型。对象

另外一方面,Object,Function,Array其实都是构造函数,由于能够直接new Object()等,因此它们都是函数,so (Object instanceof Function === true) &&(Function instanceof Object===true).blog

要注意的是,基本类型没有属性和方法,但它们能够调用对应基本包装类型的方法,能够来看下面的例子:ip

var a = 'ot';
a.age = 18;//hahahahaha, yeah, forever 18
alert(a.age);//undefined
a.length = 160;
alert(a.length);//2

第二步的a.age = 18其实在实现的时候分红三步:内存

var s1 = new String('ot');
s1.age = 18;
s1 = null;

即基本类型每次调用类型或方法都会建立新对象,随后便销毁。

一样,在alert(a.age)的时候,分为下列步骤:

var s2 = new String('ot');
alert(s2.age);
s2 = null;

由于没有对s2定义age方法,因此输出为undefined。在alert(a.length)的时候,因为s3 = new String('ot'),String有length方法,因此,会输出结果,固然,上一步的赋值操做的对象也必定已经被销毁了。

(二)引用or Copy

Clear about基本类型后,要了解的是,基本类型变量存在栈内部,每赋值一次就建立一个新的copy,而后play with itself. 而除了基本类型以外的引用类型,则存在堆内存中,只能引用。能够来看下面的例子:

var ot = new Object();//建立一个对象,把地址赋值给ot,即ot指向这个地址
var op = ot;//把ot的值赋给op,因此op也是指向那个对象
op.age = 18;
alert(ot.age);//18

op = new String('sunshine');//把新建立对象的地址赋给op, ot固然不变
alert(ot.length);//undefined

看了注释部分,相信已经能理解了。

(三)参数传递

Javascript的参数传递为值传递,咱们来看下面的例子:

function setAge(i)
{
    alert(i);//24
    i = 18;
    alert(i);//18
};

var ot = 24;
setAge(ot);

alert(ot);//24

把ot的值24传递进去,赋值给i,因而第一个alert的是24,而后i从新赋值,因而alert出来的是18,但外层的ot不受影响,由于传递值,也就是复制了分内容给i而已。

那传递的值为引用类型时会怎么样呢?先看例子:

function setName(obj)
{
    obj.name = 'ot';
};

var obj2 = new Object();
setName(obj2);
alert(obj2.name);//ot

这看起来很像是传递的是引用,由于obj.name受到改变了,但其实不是,其实仍是值,由于obj2自己的值就是新对象的地址,因此传进去的就是这个地址。

(四)回到面试题

咱们如今再来看前面的面试题:

var a = 1;
var obj = {
    b: 2
};
var fn = function () {};
fn.c = 3;

function test(x, y, z) {
    x = 4;
    y.b = 5;
    z.c = 6;
    return z;
}
test(a, obj, fn);
alert(a + obj.b + fn.c);

首先test传递进去的实参中,a是基本类型(啊对了,复制了一份值喔喔),obj是object(指向地址呼啦啦,你动我也动呢),fn也固然不是基本类型啦。在执行test的时候,x被赋值为4(跟a不要紧,各玩各的嘛,a仍然为1),y的b被赋值为5,那obj的b也变为5,z的c变为6,那fn的c固然也会是6. 因此alert的结果应该是1+5+6 =12. (其实test不返回z也同样,z仍然改变的)。

相关文章
相关标签/搜索