var foo = {n: 1};
(function(foo) {
console.log(foo.n);
foo.n = 3;
var foo = {n: 2};
console.log(foo.n);
})(foo)
console.log(foo.n);
复制代码
var foo = {n: 1};
(function(foo) {
// 形参foo 与实参foo 一样指向同一片内存空间,这个空间的n的值为1
// 优先级低于形参,无效
var foo;
// 打印1
console.log(foo.n); // 1
// 形参与实参指向的内存空间里的n的值改为3
foo.n = 3;
// 形参foo指向新的内存空间,里面n的值为2
foo = {n: 2};
// 打印新的内存空间里的n的值
console.log(foo.n); // 2
})(foo)
// 实参foo的指向还是原来的内存空间,里面的n的值为3
console.log(foo.n); // 3复制代码
2
如果该变量名的属性已经存在,为了防止同名的函数被修改为undefined,则会直接跳过,原属性值不会被修改。(在执行上下文的创建过程)
function foo() { console.log('function foo') }
var foo = 20;
console.log(foo); // 20
// foo = 20是在执行上下文的执行过程中运行的,输出结果自然会是20复制代码
console.log(foo); // function foo
function foo() { console.log('function foo') }
var foo = 20;复制代码
// 上栗的执行顺序为
// 首先将所有函数声明放入变量对象中
function foo() { console.log('function foo') }
// 其次将所有变量声明放入变量对象中,但是因为foo已经存在同名函数,因此此时会跳过undefined的赋值
// var foo = undefined;
// 然后开始执行阶段代码的执行
console.log(foo); // function foo
foo = 20;
复制代码
3
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a, b);
// a => { n: 2 }
// b => { n: 1, x: { n: 2 } }
// 直接从最后一句连续赋值开始解释,首先预解析是从左到右,连续赋值是从右到左
// 预解析的时候a.x不存在,所以 a.x 为 undefined,并存起来
// 然后从右到左赋值,a先改变了指向,这时候a = { n: 2 },b不变---
// 但是由于预解析的时候a.x已经存起来了---
// 所以a.x的a的指向还是旧地址,所以旧地址的x改变了,b指向的值也就改变了,所以出现了上面的结果
复制代码