Daily-Interview-Question
Daily-Interview-Question copied to clipboard
第 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);
http://www.baidu.com
http://www.baidu.com 函数的形参是值传递的
I think it’s baidu
http://www.baidu.com
http://www.baidu.com
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"
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“
- 解析:执行上下文的建立过程
函数的形参是值的传递,传递对象的话,函数接受的是这个对象的指针。
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);
//www.baidu.com
http://www.baidu.com 函数的形参是值传递的
感觉这么说不准确。对象传值传的是引用,但是引用是copy给函数形参。
// 这里把o改成a
// webSite引用地址的值copy给a了
function changeObjProperty(a) {
// 改变对应地址内的对象属性值
a.siteUrl = "http://www.baidu.com"
// 变量a指向新的地址 以后的变动和旧地址无关
a = new Object()
a.siteUrl = "http://www.google.com"
a.name = 456
}
var webSite = new Object();
webSite.name = '123'
changeObjProperty(webSite);
console.log(webSite); // {name: 123, siteUrl: 'http://www.baidu.com'}
传进函数的是原对象的地址(或者说引用),这个地址赋值给了形参(形参看做局部变量),形参变量此时指向原对象,后面o=new object的时候,形参变量保存的是新对象的地址,指向的是新的对象,所以第二次的o.siteUrl 也是给这个新对象属性的赋值,和旧对象无关。最后打印website.SiteUrl 的时候,访问的是旧对象,因为前面的改动都只涉及到形参变量,和website无关,website依然保存着旧对象的引用。
http://www.baidu.com webSite属于复合数据类型,函数参数中以地址传递,修改值会影响到原始值,但如果将其完全替换成另一个值,则原来的值不会受到影响
输出http://www.baidu.com,入参是对象到话,传递到是引用复制, o.siteUrl = "http://www.baidu.com",是改变了实际到内存值,o = new Object()则改变该引用指向,所以o.siteUrl = "http://www.google.com"不会改变值
function(o) 里 o形参是一个LHS查询 相当于 function() { var o = 实参 } 这个题目可以用这样一个角度看 var o = website; o.siteurl = 'baidu'; o = new Object() console.log(website.siteurl) // '百度'
function changeObjProperty(o) { // 指向内存中的对象,在这里叫做引用o1, o是函数内的一个声明的对象,与下面传进来的webSite的引用相同
o.siteUrl = "http://www.baidu.com" // 引用在引用o1上加属性
o = new Object() // 这里是引用o2,与下面webSite的引用不同了
o.siteUrl = "http://www.google.com" // 引用o2上加属性
}
let webSite = new Object(); // webSite的引用一直是o1,没改变过
changeObjProperty(webSite);
console.log(webSite.siteUrl); // 所以是baidu.com
- 答案:”http://www.baidu.com“
- 解析:执行上下文的建立过程
请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗? 那console.log(website.siteUrl);这步的时候前面的代码已经执行了啊?为什么执行阶段也不覆盖呢?
- 答案:”http://www.baidu.com“
- 解析:执行上下文的建立过程
请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗? 那console.log(website.siteUrl);这步的时候前面的代码已经执行了啊?为什么执行阶段也不覆盖呢?
我觉得覆盖是对于同一个函数级作用域而言的
- 答案:”http://www.baidu.com“
- 解析:执行上下文的建立过程
请教一下,是因为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
function changeObjProperty(o, str) {
console.log(copy === o) // true
o.siteUrl = "http://www.baidu.com"
o = new Object()
o.siteUrl = "http://www.google.com"
str = 456;
}
let webSite = new Object();
let copy = webSite
let str = '123'
console.log(copy === webSite) // true
changeObjProperty(webSite, str);
console.log(webSite.siteUrl); // http://www.baidu.com
console.log(str) // '123'
函数传参,引用类型 copy 对象指向的内存地址,基本类型 copy 值
一开始真没转过弯来,实践了一下,才明白过来,顺便在这里记录一下:
先让我改造一下:
function changeObjProperty(o) {
// o这个形参实际可以写成var o = webSite
o.siteUrl = "http://www.baidu.com";
// 偷偷添加一行代码,此时website和o指向同一个堆地址
// website.siteUrl = "http://www.baidu.com";
o = new Object() // 相当于 o = {}, o 移情别恋到新的对象引用上去了,而webSite还死心塌地之前的对象引用,因此分道扬镳了
o.siteUrl = "http://www.google.com"
return o;
}
let webSite = new Object(); // let webSite = {}
changeObjProperty(webSite);
console.log(webSite.siteUrl); // http://www.baidu.com
let newo = changeObjProperty(webSite);
console.log(newo.siteUrl) // "http://www.google.com"
因为website是引用类型,o只是对website的引用,改变引用类型的属性可以,但如果o重新赋值相当于重新开辟一块地址,不影响外面的对象(website还是指向原来的地址)
函数的形参与实参修改并非双向~~ 正常编程时,不应该修改命名形参;arguments对象中的实参值,都应该作为只读常量来处理 function doAdd(num1, num2) { arguments[1] = 10 num1 = 50 console.log(arguments[0] + num2) } doAdd(10, 20) //60
var o = {}
var o1 = o
o.name = "张三"
o1 = {}
o1.name = "李四"
console.log(o.name)
//o1就可以理解为在函数中使用的形参
//传参也是一个变量向另一个变量赋值的过程,当类型为引用类型时,传递的是指针
传递参数: ECMAScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个 变量复制到另一个变量一样。基本类型的传递如同基本类型变量的复制一样,而引用类型的值传递,如同引用类型变量的复制一样 可能会困惑:因为访问变量有按值和按引用两种方式,而参数只能按值传递。 会错误的认为:在局部作用域中修改的对象会在全局作用域中反映出来,就说明参数是按引用传递的 证明对象是按值传递的:
` function setName(obj)
{
obj.name='Jack';
obj=new Object();
obj.name='Bob';
}
var person=new Person();
setName(person);
console.log(person.name); 输出Jack`
此例子在《js高级程序设计》一书里面有解释
// o 是对象webSite的引用
function changeObjProperty(o) {
// 给webSite的属性siteUrl赋值
o.siteUrl = "http://www.baidu.com"
// 创建新对象,新引用并赋值给o,下o非上o
o = new Object()
// 给新引用添加属性siteUrl并赋值,和webSite无关
o.siteUrl = "http://www.google.com"
}
let webSite = new Object();
// webSite 是个对象,以形参传递,传递的是webSite的引用
changeObjProperty(webSite);
console.log(webSite.siteUrl)
baidu
有些同学可能把[引用类型]和[按引用传递]混淆了 js里函数都是按值传递的
函数中的变量o是局部变量,一开始只是和website指向同一个内存,接着局部变量o指向了新的内存(o = new Object()),所以当再次给o添加属性时,由于指向的内存已经和website不一样了,所以website的属性并不会被修改。