第 98 题:写出如下代码的打印结果
function changeObjProperty(o) { o.siteUrl = "http://www.baidu.com" o = new Object() o.siteUrl = "http://www.google.com" } let webSite = new Object(); changeObjProperty(webSite); console.log(webSite.siteUrl);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 第 99 题:编程算法题
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(42)
function(o) 里 o形参是一个LHS查询 相当于 function() { var o = 实参 }
这个题目可以用这样一个角度看
var o = website;
o.siteurl = 'baidu';
o = new Object()
console.log(website.siteurl) // '百度'
请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗?
那console.log(website.siteUrl);这步的时候前面的代码已经执行了啊?为什么执行阶段也不覆盖呢?
我觉得覆盖是对于同一个函数级作用域而言的
抱歉,这里是我看错了题目,我前面看成题目是
var o = new Object()
,理解方向错了。实际上本题的关键应该是变量o所指向的内存(对象)发生了变化。www.baidu.com 形参按值传
function changeObjProperty(o) {
o.siteUrl = "http://www.baidu.com" //给webSite的siteUrl属性赋值
o = new Object() //修改o的引用,此时o与webSite无关了
o.siteUrl = "http://www.google.com" //给新o赋值
}
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl); //http://www.baidu.com
函数传参,引用类型 copy 对象指向的内存地址,基本类型 copy 值
一开始真没转过弯来,实践了一下,才明白过来,顺便在这里记录一下:
先让我改造一下:
因为website是引用类型,o只是对website的引用,改变引用类型的属性可以,但如果o重新赋值相当于重新开辟一块地址,不影响外面的对象(website还是指向原来的地址)
函数的形参与实参修改并非双向~~
正常编程时,不应该修改命名形参;arguments对象中的实参值,都应该作为只读常量来处理
function doAdd(num1, num2) {
arguments[1] = 10
num1 = 50
console.log(arguments[0] + num2)
}
doAdd(10, 20) //60
传递参数:
ECMAScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个
变量复制到另一个变量一样。基本类型的传递如同基本类型变量的复制一样,而引用类型的值传递,如同引用类型变量的复制一样
可能会困惑:因为访问变量有按值和按引用两种方式,而参数只能按值传递。
会错误的认为:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的
证明对象是按值传递的:
此例子在《js高级程序设计》一书里面有解释
baidu
有些同学可能把[引用类型]和[按引用传递]混淆了 js里函数都是按值传递的
函数中的变量o是局部变量,一开始只是和website指向同一个内存,接着局部变量o指向了新的内存(o = new Object()),所以当再次给o添加属性时,由于指向的内存已经和website不一样了,所以website的属性并不会被修改。
一开始, webSite 和 o 指向的是同一个地址,所以当 o.siteUrl = "http://www.baidu.com" 时, webSite 也共享到了这个 siteUrl : "http://www.baidu.com" 的值。
执行o = new Object(),此时的 o 指向了一个新的地址,webSite 不再和 o 共享数据了,之后 o 再怎么操作都对 webSite 都没有影响了。
所以 webSite.siteUrl = "http://www.baidu.com"
刚开始a的地址跟webSite的地址一样,假设都指向AAAAAA,AAAAAA里面存的是{siteUrl:"http://www.baidu.com"},后面a指向了新的地址假设叫BBBBBB。BBBBBB里面存的是{siteUrl : "http://www.google.com"},但是webSite指向的地址一直没变始终是AAAAAA
非常nice 这个题目和
var a = { n: 1 };
var b = a;
a.x = a = { n: 2 };
console.log(a.x) // undefined
console.log(b.x) // {n:2}
这种类似
写出如下代码的打印结果
参考
传递参数:
ECMAScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个
变量复制到另一个变量一样。基本类型的传递如同基本类型变量的复制一样,而引用类型的值传递,如同引用类型变量的复制一样
打印的肯定是百度。
至于为什么?
在《JS高程》里,第三版4.1.3里面说到,
但是回到这个问题下面,这个参数看起来像是引用传递, 其实传递的不是引用, 而是引用的一个副本。可以称之为共享传递。但是这个引用的副本传递,也可以叫做按值传递, 所以红宝书也没说错。所在在这一句
o.siteUrl = 'http://www.baidu.com'
确实把
webSite.siteUrl
改成了baidu。但是后续的参数o又指向了新的对象地址。let a = {}
let b = a
b.name = 'cc'
b = {}
b.name = 'ww'
console.log(a.name) // cc
console.log(b.name) // ww
参数
o
是函数内部的变量;第一次修改
o.siteUrl
时,o
与webSit
为同一个对象的引用,所以会影响到外面的webSite
对象;函数第二行给
o
赋值了一个新对象,此时o
与webSite
就是不同对象的引用了;最后修改
o
时,改变的是新对象的siteUrl
,而不会影响到外面的webSite
;ECMAScript 中所有函数的参数都是按值传递的。
输出http://www.baidu.com,入参是对象到话,传递到是引用复制, o.siteUrl = "http://www.baidu.com",是改变了实际到内存值,o = new Object()则改变该引用指向,所以o.siteUrl = "http://www.google.com"不会改变值
http://www.baidu.com webSite属于复合数据类型,函数参数中以地址传递,修改值会影响到原始值,但如果将其完全替换成另一个值,则原来的值不会受到影响
传进函数的是原对象的地址(或者说引用),这个地址赋值给了形参(形参看做局部变量),形参变量此时指向原对象,后面o=new object的时候,形参变量保存的是新对象的地址,指向的是新的对象,所以第二次的o.siteUrl 也是给这个新对象属性的赋值,和旧对象无关。最后打印website.SiteUrl 的时候,访问的是旧对象,因为前面的改动都只涉及到形参变量,和website无关,website依然保存着旧对象的引用。
感觉这么说不准确。对象传值传的是引用,但是引用是copy给函数形参。
函数的形参是值的传递,传递对象的话,函数接受的是这个对象的指针。
所以下面谷歌的赋值是指向新的对象的赋值吗?
function changeObjProperty(o) {
o.siteUrl = "http://www.baidu.com"
o = new Object() // 形参 o 的指向发生改变,指向堆内存中一个新的对象
o.siteUrl = "http://www.google.com"
}
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl); //"http://www.baidu.com"
http://www.baidu.com
http://www.baidu.com
I think it’s baidu
http://www.baidu.com
函数的形参是值传递的
http://www.baidu.com