Daily-Interview-Question icon indicating copy to clipboard operation
Daily-Interview-Question copied to clipboard

第 98 题:写出如下代码的打印结果

Open yygmind opened this issue 5 years ago • 45 comments

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);

yygmind avatar Jul 03 '19 14:07 yygmind

http://www.baidu.com

fuqianxi avatar Jul 04 '19 01:07 fuqianxi

http://www.baidu.com 函数的形参是值传递的

BaoTao1997 avatar Jul 04 '19 01:07 BaoTao1997

I think it’s baidu

bfrontend avatar Jul 04 '19 01:07 bfrontend

http://www.baidu.com

jefferyE avatar Jul 04 '19 01:07 jefferyE

http://www.baidu.com

Kian-404 avatar Jul 04 '19 01:07 Kian-404

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"

Anno59 avatar Jul 04 '19 01:07 Anno59

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"

所以下面谷歌的赋值是指向新的对象的赋值吗?

y1324 avatar Jul 04 '19 01:07 y1324

lhj767382286 avatar Jul 04 '19 01:07 lhj767382286

函数的形参是值的传递,传递对象的话,函数接受的是这个对象的指针。

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

AnsonZnl avatar Jul 04 '19 01:07 AnsonZnl

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'}

WanderHuang avatar Jul 04 '19 01:07 WanderHuang

image

lubaichong110 avatar Jul 04 '19 01:07 lubaichong110

传进函数的是原对象的地址(或者说引用),这个地址赋值给了形参(形参看做局部变量),形参变量此时指向原对象,后面o=new object的时候,形参变量保存的是新对象的地址,指向的是新的对象,所以第二次的o.siteUrl 也是给这个新对象属性的赋值,和旧对象无关。最后打印website.SiteUrl 的时候,访问的是旧对象,因为前面的改动都只涉及到形参变量,和website无关,website依然保存着旧对象的引用。

Chorer avatar Jul 04 '19 02:07 Chorer

http://www.baidu.com webSite属于复合数据类型,函数参数中以地址传递,修改值会影响到原始值,但如果将其完全替换成另一个值,则原来的值不会受到影响

HduSy avatar Jul 04 '19 02:07 HduSy

输出http://www.baidu.com,入参是对象到话,传递到是引用复制, o.siteUrl = "http://www.baidu.com",是改变了实际到内存值,o = new Object()则改变该引用指向,所以o.siteUrl = "http://www.google.com"不会改变值

TNTrocket avatar Jul 04 '19 02:07 TNTrocket

function(o) 里 o形参是一个LHS查询 相当于 function() { var o = 实参 } 这个题目可以用这样一个角度看 var o = website; o.siteurl = 'baidu'; o = new Object() console.log(website.siteurl) // '百度'

xiaoyangdian avatar Jul 04 '19 07:07 xiaoyangdian

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

alowkeyguy avatar Jul 04 '19 08:07 alowkeyguy

请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗? 那console.log(website.siteUrl);这步的时候前面的代码已经执行了啊?为什么执行阶段也不覆盖呢?

0820Jones avatar Jul 04 '19 10:07 0820Jones

请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗? 那console.log(website.siteUrl);这步的时候前面的代码已经执行了啊?为什么执行阶段也不覆盖呢?

我觉得覆盖是对于同一个函数级作用域而言的

xiaoyangdian avatar Jul 04 '19 10:07 xiaoyangdian

请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗? 那console.log(website.siteUrl);这步的时候前面的代码已经执行了啊?为什么执行阶段也不覆盖呢?

抱歉,这里是我看错了题目,我前面看成题目是 var o = new Object(),理解方向错了。实际上本题的关键应该是变量o所指向的内存(对象)发生了变化。

lhj767382286 avatar Jul 04 '19 10:07 lhj767382286

www.baidu.com 形参按值传

sohoorc avatar Jul 04 '19 11:07 sohoorc

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

Weathers0086 avatar Jul 09 '19 02:07 Weathers0086

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 值

wwervin72 avatar Jul 09 '19 03:07 wwervin72

一开始真没转过弯来,实践了一下,才明白过来,顺便在这里记录一下:

先让我改造一下:

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"

mongonice avatar Jul 09 '19 07:07 mongonice

因为website是引用类型,o只是对website的引用,改变引用类型的属性可以,但如果o重新赋值相当于重新开辟一块地址,不影响外面的对象(website还是指向原来的地址)

vimplus avatar Jul 10 '19 05:07 vimplus

函数的形参与实参修改并非双向~~ 正常编程时,不应该修改命名形参;arguments对象中的实参值,都应该作为只读常量来处理 function doAdd(num1, num2) { arguments[1] = 10 num1 = 50 console.log(arguments[0] + num2) } doAdd(10, 20) //60

icdong avatar Jul 10 '19 15:07 icdong

var o = {}


var o1 = o
o.name = "张三"
o1 = {}
o1.name = "李四"

console.log(o.name)

//o1就可以理解为在函数中使用的形参
//传参也是一个变量向另一个变量赋值的过程,当类型为引用类型时,传递的是指针

defypro avatar Jul 17 '19 07:07 defypro

传递参数: 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高级程序设计》一书里面有解释

sunhanA avatar Jul 25 '19 10:07 sunhanA

// 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)

xing-zlear avatar Aug 15 '19 11:08 xing-zlear

baidu
有些同学可能把[引用类型]和[按引用传递]混淆了 js里函数都是按值传递的

DarthVaderrr avatar Aug 26 '19 07:08 DarthVaderrr

函数中的变量o是局部变量,一开始只是和website指向同一个内存,接着局部变量o指向了新的内存(o = new Object()),所以当再次给o添加属性时,由于指向的内存已经和website不一样了,所以website的属性并不会被修改。

chenxiaoleizi avatar Sep 30 '19 03:09 chenxiaoleizi