Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
yygmind opened this issue Jul 3, 2019 · 45 comments
Open

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

yygmind opened this issue Jul 3, 2019 · 45 comments
Labels

Comments

@yygmind
Copy link
Contributor

yygmind commented Jul 3, 2019

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);
@fuqianxi
Copy link

fuqianxi commented Jul 4, 2019

http://www.baidu.com

@BaoTao1997
Copy link

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

@bfrontend
Copy link

I think it’s baidu

@jefferyE
Copy link

jefferyE commented Jul 4, 2019

http://www.baidu.com

1 similar comment
@Kian-404
Copy link

Kian-404 commented Jul 4, 2019

http://www.baidu.com

@Anno59
Copy link

Anno59 commented Jul 4, 2019

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
Copy link

y1324 commented Jul 4, 2019

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"

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

@lhj767382286
Copy link

@AnsonZnl
Copy link

AnsonZnl commented Jul 4, 2019

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

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

@WanderHuang
Copy link

WanderHuang commented Jul 4, 2019

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

@lubaichong110
Copy link

image

@Chorer
Copy link

Chorer commented Jul 4, 2019

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

@HduSy
Copy link

HduSy commented Jul 4, 2019

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

@TNTrocket
Copy link

@xiaoyangdian
Copy link

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

@alowkeyguy
Copy link

alowkeyguy commented Jul 4, 2019

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

@0820Jones
Copy link

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

@xiaoyangdian
Copy link

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

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

@lhj767382286
Copy link

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

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

@sohoorc
Copy link

sohoorc commented Jul 4, 2019

www.baidu.com 形参按值传

@Weathers0086
Copy link

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

@wwervin72
Copy link

wwervin72 commented Jul 9, 2019

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 值

@mongonice
Copy link

mongonice commented Jul 9, 2019

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

先让我改造一下:

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"

@vimplus
Copy link

vimplus commented Jul 10, 2019

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

@icdong
Copy link

icdong commented Jul 10, 2019

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

@defypro
Copy link

defypro commented Jul 17, 2019

var o = {}


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

console.log(o.name)

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

@sunhanA
Copy link

sunhanA commented Jul 25, 2019

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

@xing-zlear
Copy link

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

@DarthVaderrr
Copy link

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

@chenxiaoleizi
Copy link

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

@Qlly-web
Copy link

Qlly-web commented Mar 7, 2020

一开始, 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"

@kiliaosi
Copy link

kiliaosi commented Mar 10, 2020

function changeObjProperty(o) {
  //函数参数可以理解为局部变量,传入引用类型执行时,可以理解为:局部变量o与全局变量website同时指向同一个对象
//o现在是引用类型,更改成功,siteUrl = "http://www.baidu.com"
  o.siteUrl = "http://www.baidu.com"
  //更改局部变量o的指向,指向一个新的对象
  o = new Object()
//更改局部变量o指向的新的对象的siteUrl="http://www.google.com"
  o.siteUrl = "http://www.google.com"
//函数执行结束,局部变量o以及指向的新对象释放
} 
//初始化变量
let webSite = new Object();
//进入change调用
changeObjProperty(webSite);

//打印:"http://www.baidu.com"
console.log(webSite.siteUrl);

@yangqianlu
Copy link

刚开始a的地址跟webSite的地址一样,假设都指向AAAAAA,AAAAAA里面存的是{siteUrl:"http://www.baidu.com"},后面a指向了新的地址假设叫BBBBBB。BBBBBB里面存的是{siteUrl : "http://www.google.com"},但是webSite指向的地址一直没变始终是AAAAAA

@fariellany
Copy link

// 这里把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'}

非常nice 这个题目和
var a = { n: 1 };
var b = a;
a.x = a = { n: 2 };
console.log(a.x) // undefined
console.log(b.x) // {n:2}
这种类似

@soraly
Copy link

soraly commented Jul 20, 2020

写出如下代码的打印结果

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);
  • webSite该对象的地址传给了变量o
  • 改变o的siteUrl时webSite对应的也改了
  • o = new Object()相当于改变了o的地址,这以后的赋值操作和webSite 都无关了
  • 所以打印webSite.siteUrl就是"http://www.baidu.com"

参考

传递参数:
ECMAScript中所有函数的参数都是按值传递的。也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个
变量复制到另一个变量一样。基本类型的传递如同基本类型变量的复制一样,而引用类型的值传递,如同引用类型变量的复制一样

@songbing1990
Copy link

songbing1990 commented Sep 19, 2020

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改成a
function changeObjProperty(a) {
  /**
   * JS 函数预编译(解析)
   * 
   * 1、执行前的一瞬间,会生成一个AO(action object)对象
   * 2、将函数内的形参和变量声明存储到AO对象中,值为undefined
   * 3、将实参和形参统一,形参作为AO对象的属性名,实参作为AO对象的属性值
   * 
   * ① AO = {}
   * 
   * ① 形成一个局部变量a(形参)
   *   AO = { a: undefined }
   * 
   * ② 把形参与实参结合,即局部变量a与外部变量webSite指向的是同一块堆内存
   *   AO = { a: o的引用地址 }
   */

  // 改变a对象里的值,即改变webSite对象中的值
  a.siteUrl = "http://www.baidu.com"

  // 更改局部变量a的引用,指向新的对象,之后与webSite对象无关
  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'}

@XuedaoYuan
Copy link

XuedaoYuan commented Sep 24, 2020

打印的肯定是百度。
至于为什么?
在《JS高程》里,第三版4.1.3里面说到,

ES的所有函数的参数都是按值传递

但是回到这个问题下面,这个参数看起来像是引用传递, 其实传递的不是引用, 而是引用的一个副本。可以称之为共享传递。但是这个引用的副本传递,也可以叫做按值传递, 所以红宝书也没说错。所在在这一句
o.siteUrl = 'http://www.baidu.com'
确实把webSite.siteUrl改成了baidu。但是后续的参数o又指向了新的对象地址。

@huxiaocheng
Copy link

huxiaocheng commented Feb 19, 2021

let a = {}
let b = a
b.name = 'cc'
b = {}
b.name = 'ww'
console.log(a.name) // cc
console.log(b.name) // ww

@WayneGongCN
Copy link

参数 o 是函数内部的变量;
第一次修改 o.siteUrl 时,owebSit 为同一个对象的引用,所以会影响到外面的 webSite 对象;
函数第二行给 o 赋值了一个新对象,此时 owebSite 就是不同对象的引用了;
最后修改 o 时,改变的是新对象的 siteUrl ,而不会影响到外面的 webSite

@xlb233
Copy link

xlb233 commented Mar 9, 2021

// 参数按值传递
// 若传入基本类型值,那么函数参数的值就是传入的值
// 若传入引用类型值,那么函数参数的值是该引用类型值的内存地址
function changeObjProperty(o) {
  // 给传入对象的siteUrl属性赋值为"http://www.baidu.com"
  // 此时webSite对象新增了一个属性siteUrl,值为百度
  o.siteUrl = "http://www.baidu.com"
  // 参数o可以视为一个局部变量,其当前值为webSite对象的内存地址
  // 给o重新复制为空对象的内存地址,从此webSite对象与o无关
  o = new Object()
  o.siteUrl = "http://www.google.com"
} 
let webSite = new Object();
// 将引用类型值webSite传入changeObjProperty函数中
changeObjProperty(webSite);
console.log(webSite.siteUrl); // 百度

@silverWolf818
Copy link

ECMAScript 中所有函数的参数都是按值传递的。

@ruanlinxin
Copy link

function changeObjProperty(o) {
// 这里的o相当于接收了一个内存地址
  o.siteUrl = "http://www.baidu.com"
// 修改了对于内存地址的参数
  o = new Object()
// 修改了0的内存地址指向
  o.siteUrl = "http://www.google.com"
// 修改新地址的siteUrl
} 
let webSite = new Object();
changeObjProperty(webSite);
console.log(webSite.siteUrl);

@Yangfan2016
Copy link

https://juejin.cn/post/6844903929470271501

js 函数里是 按值传递 的
只不过 对象 传的是 指针的 拷贝 值

@Micah-Yu
Copy link

Micah-Yu commented Sep 17, 2022

函数预编译

  1. 创建AO(Activation object)对象
  2. 找形参和变量声明,将变量和形参名作为AO属性名,值为underfind
  3. 将实参和形参统一
  4. 找函数声明,函数体作为值附值
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);

所以函数内部整个过程的大致过程如下

  1. 预编译阶段

    var o = undefined //声明形参 o
    
    o = webSite // 形参和实参相统一, 此时变量o和变量webSite指向同一个地址,值为 new Object() 的返回值,即 {}

也就是说,函数的形参会在函数的内部声明同名变量,所以 owebSite 为两个不同的变量

  1. 执行阶段

    o.siteUrl = "http://www.baidu.com" //变量o和变量webSite都指向同一个地址,所以他们的值都为 {siteUrl: "http://www.baidu.com"}
    
    o = new Object() // 变量o指向新的地址(o = {}),webSite指向仍然不变(webSite = {siteUrl: "http://www.baidu.com"}),所有后面对o的操作都不会影响webSite

@defypro
Copy link

defypro commented Oct 11, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests