84669 人學習
152542 人學習
20005 人學習
5487 人學習
7821 人學習
359900 人學習
3350 人學習
180660 人學習
48569 人學習
18603 人學習
40936 人學習
1549 人學習
1183 人學習
32909 人學習
function box(obj){ obj.name='Lee'; var obj = new Object(); obj.name='kkk'; } var obj = new Object(); box(obj); alert(obj.name);
lee
我这么说好不好,
我给了你一个苹果A,让你在上面刻个lee,你刻了;然后扔掉这个苹果,自己又拿了一个苹果B,在上面刻了kkk。
kkk
现在问你,我之前给你的苹果A上,刻的什么?
box(obj);
这个obj可以看作obj1,他的父作用域是window;
function box(obj){ obj.name='Lee'; //这里重新定义了obj父作用域为box var obj = new Object(); // 此时的obj.name是box函数的局部变量; obj.name='kkk'; }
所以打印是lee而不是kkk
上面说到变量提升,那么提升后应该是这样:
function box(obj) { var obj; obj.name = 'Lee'; obj = new Object(); obj.name = 'kkk'; } var obj = new Object(); box(obj); console.log(obj.name);
OK,然后让我用简单粗暴的办法,在box()里面插几条console.log(obj),然后在全局的obj声明之后给 name 属性赋个值。就变成这样:
box()
console.log(obj)
obj
function box(obj) { var obj; console.log(obj); obj.name = 'Lee'; console.log(obj); obj = new Object(); console.log(obj); obj.name = 'kkk'; console.log(obj); } var obj = new Object(); obj.name = 'test'; box(obj); console.log(obj.name); // 返回的结果 // { name: 'test' } // { name: 'Lee' } // {} // { name: 'kkk' } // Lee
可以看到,即使box()中声明的obj提升到函数顶部,后面 log 出来的依旧还是传入的obj。提升后的变量声明由于已经存在了传入的obj,所以实质上这句是没用的。
虽然函数的参数是按值传递的,但是对象的值其实是内存中的指针地址,所以函数中的obj(未在函数中再次赋值之前)与全局作用域obj实际上是同一个。
参考:javascript传递参数如果是object的话,是按值传递还是按引用传递?
在函数中再次赋值之后,obj变成了这个局部作用域中的变量(new了一个新的Object,并赋值给了obj。obj的值不再指向全局作用域下的obj),所以后面再怎么修改都跟全局作用域下的obj没有关系了。
new
Object
以上是查阅以及测试之后,思考得出。如果有地方不对,望高人指点。
var obj = new Object(); obj.name='kkk';
这个地方的obj可以看做遮盖了上面的obj对象, 于是下面的语句操作的是这个内部的局部变量.
遮盖
多谢指出传送都是按值传送,只是对象,数组等传送的是其内容的地址
obj.name='Lee'
这时obj指向的是外面那个obj,对外面obj的name赋值
var obj=new Object();
此时obj指向的是一个新的对象,一个和外面obj不一样的对象
obj.name='kkk';
新对象的name赋值
so,外面的obj对象赋值后就没有改变过
首先说明两点:
使用var声明的变量会存在声明提前
函数的参数会有声明变脸的效果
根据上述两点变量已经声明了变量obj,那个var obj = new Object()等价于obj = new Object();
var obj = new Object()
obj = new Object()
function box(obj){ obj.name='Lee';//此处的obj为传入的值 obj = new Object(); //此处将obj覆盖 obj.name='kkk';//这里的obj为后面新建的obj } box(obj); console.log(obj.name);//弹出外面的obj的name
还有函数传值全部是按值传递,没有按引用传递
这道题应该考察的是javascript函数调用的参数传递方式。看回答的人也有说到这一点的,但是说错了,这里给出正确的说法,以免其他人被带入歧途。javascript其实和java一样,参数传递只有一种形式:值传递,如果传入参数是对象,参数实际上是该对象的引用的copy。知道这一点这道题就不会错了。@tudewutong 能想到声明前置,我还真没想到这一点。从这道题可以看出来,再声明前置之后接着就把声明的变量的引用值赋予了函数参数的引用,不知道是不是这样,还让高人指点。
补充一下,关于声明提前的,提前的只是声明,不包括赋值。
函数里定义的var obj=new Object()局部变量在函数外是不能被引用的
var obj=new Object()
obj这个对象的名字和参数名字重复了,参数名重新换个名字就能区分开了,因为你始终都用的obj这个名字.就像是夫妻俩已经有一个儿子了,叫张三,后来有怀了一个孩子,夫妇俩商量叫啥,俩人嫌麻烦就又给还怀着的孩子也起了个名字叫“张三”,你说这俩孩子是同一个人吗,还是别把俩孩子的名字起成一样的了吧,明白我说的意思了吗?
我这么说好不好,
我给了你一个苹果A,让你在上面刻个
lee
,你刻了;然后扔掉这个苹果,自己又拿了一个苹果B,在上面刻了kkk
。现在问你,我之前给你的苹果A上,刻的什么?
这个obj可以看作obj1,他的父作用域是window;
所以打印是
lee
而不是kkk
上面说到变量提升,那么提升后应该是这样:
OK,然后让我用简单粗暴的办法,在
box()
里面插几条console.log(obj)
,然后在全局的obj
声明之后给 name 属性赋个值。就变成这样:可以看到,即使
box()
中声明的obj
提升到函数顶部,后面 log 出来的依旧还是传入的obj
。提升后的变量声明由于已经存在了传入的obj
,所以实质上这句是没用的。虽然函数的参数是按值传递的,但是对象的值其实是内存中的指针地址,所以函数中的
obj
(未在函数中再次赋值之前)与全局作用域obj
实际上是同一个。在函数中再次赋值之后,
obj
变成了这个局部作用域中的变量(new
了一个新的Object
,并赋值给了obj
。obj
的值不再指向全局作用域下的obj
),所以后面再怎么修改都跟全局作用域下的obj
没有关系了。以上是查阅以及测试之后,思考得出。如果有地方不对,望高人指点。
这个地方的obj可以看做
遮盖
了上面的obj对象, 于是下面的语句操作的是这个内部的局部变量.多谢指出
传送都是按值传送,只是对象,数组等传送的是其内容的地址
这时obj指向的是外面那个obj,对外面obj的name赋值
此时obj指向的是一个新的对象,一个和外面obj不一样的对象
新对象的name赋值
so,外面的obj对象赋值后就没有改变过
首先说明两点:
使用var声明的变量会存在声明提前
函数的参数会有声明变脸的效果
根据上述两点变量已经声明了变量obj,那个
var obj = new Object()
等价于obj = new Object()
;还有函数传值全部是按值传递,没有按引用传递
这道题应该考察的是javascript函数调用的参数传递方式。看回答的人也有说到这一点的,但是说错了,这里给出正确的说法,以免其他人被带入歧途。
javascript其实和java一样,参数传递只有一种形式:值传递,如果传入参数是对象,参数实际上是该对象的引用的copy。知道这一点这道题就不会错了。
@tudewutong 能想到声明前置,我还真没想到这一点。从这道题可以看出来,再声明前置之后接着就把声明的变量的引用值赋予了函数参数的引用,不知道是不是这样,还让高人指点。
补充一下,关于声明提前的,提前的只是声明,不包括赋值。
函数里定义的
var obj=new Object()
局部变量在函数外是不能被引用的obj这个对象的名字和参数名字重复了,参数名重新换个名字就能区分开了,因为你始终都用的obj这个名字.
![](http://img.php.cn/upload/image/000/000/000/ad93505af957f1d43d98dbbda6e0691b-0.png)
就像是夫妻俩已经有一个儿子了,叫张三,后来有怀了一个孩子,夫妇俩商量叫啥,俩人嫌麻烦就又给还怀着的孩子也起了个名字叫“张三”,你说这俩孩子是同一个人吗,还是别把俩孩子的名字起成一样的了吧,明白我说的意思了吗?