-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
Comments
http://www.baidu.com |
I think it’s baidu |
1 similar comment
function changeObjProperty(o) { |
所以下面谷歌的赋值是指向新的对象的赋值吗? |
|
函数的形参是值的传递,传递对象的话,函数接受的是这个对象的指针。
|
感觉这么说不准确。对象传值传的是引用,但是引用是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 = 实参 } |
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 |
请教一下,是因为o.siteUrl是变量声明,所以建立阶段不会被覆盖吗? |
我觉得覆盖是对于同一个函数级作用域而言的 |
抱歉,这里是我看错了题目,我前面看成题目是 |
www.baidu.com 形参按值传 |
function changeObjProperty(o) { |
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还是指向原来的地址) |
函数的形参与实参修改并非双向~~ |
var o = {}
var o1 = o
o.name = "张三"
o1 = {}
o1.name = "李四"
console.log(o.name)
//o1就可以理解为在函数中使用的形参
//传参也是一个变量向另一个变量赋值的过程,当类型为引用类型时,传递的是指针 |
传递参数:
此例子在《js高级程序设计》一书里面有解释 |
|
baidu |
函数中的变量o是局部变量,一开始只是和website指向同一个内存,接着局部变量o指向了新的内存(o = new Object()),所以当再次给o添加属性时,由于指向的内存已经和website不一样了,所以website的属性并不会被修改。 |
一开始, webSite 和 o 指向的是同一个地址,所以当 o.siteUrl = "http://www.baidu.com" 时, webSite 也共享到了这个 siteUrl : "http://www.baidu.com" 的值。 |
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); |
刚开始a的地址跟webSite的地址一样,假设都指向AAAAAA,AAAAAA里面存的是{siteUrl:"http://www.baidu.com"},后面a指向了新的地址假设叫BBBBBB。BBBBBB里面存的是{siteUrl : "http://www.google.com"},但是webSite指向的地址一直没变始终是AAAAAA |
非常nice 这个题目和 |
写出如下代码的打印结果
参考传递参数: |
// 这里把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'} |
打印的肯定是百度。
但是回到这个问题下面,这个参数看起来像是引用传递, 其实传递的不是引用, 而是引用的一个副本。可以称之为共享传递。但是这个引用的副本传递,也可以叫做按值传递, 所以红宝书也没说错。所在在这一句 |
let a = {} |
参数 |
// 参数按值传递
// 若传入基本类型值,那么函数参数的值就是传入的值
// 若传入引用类型值,那么函数参数的值是该引用类型值的内存地址
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); // 百度 |
ECMAScript 中所有函数的参数都是按值传递的。 |
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); |
https://juejin.cn/post/6844903929470271501 js 函数里是 按值传递 的 |
函数预编译
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); 所以函数内部整个过程的大致过程如下
|
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
The text was updated successfully, but these errors were encountered: