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);
以上 JavaScript 代码,在浏览器中运行的结果是
var foo = {n:1}; (function(foo){ //形参foo同实参foo一样指向同一片内存空间,这个空间里的n的值为1 var foo; //优先级低于形参,无效。 console.log(foo.n); //输出1 foo.n = 3; //形参与实参foo指向的内存空间里的n的值被改为3 foo = {n:2}; //形参foo指向了新的内存空间,里面n的值为2. console.log(foo.n); //输出新的内存空间的n的值 })(foo); console.log(foo.n); //实参foo的指向还是原来的内存空间,里面的n的值为3.
本质:只提升声明部分
1.我是变量声明,我会被提升在作用域顶端!
var a;
2.我是变量定义,我的声明部分会被提升,赋值部分不会被提升!
var b = 'test';
3.我是函数定义,或者叫我函数表达式。其实我就是变量定义,只不过恰好被赋值的类型是函数,所以也只提升变量名
,不提升函数值
!
var c = function() {
console.log('test');
}
4.我是函数声明,所以我全部被提升了
,包括函数名和函数体。另外,我的优先级比变量声明要高,名字和我相同的变量声明会被忽略!
function d() {
console.log('test');
}
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);
结果: 1 2 3
var foo=1;
(function (foo) {
console.log(foo);
foo=3;
var foo=2;
console.log(foo);
})(foo);
console.log(foo);
结果:1 2 1
解释:
var foo={n:"我是形参或全局变量"};
(function (foo) {
console.log(foo.n);
foo.n="我改变了参数和全局变量";
var foo={n:"我是局部变量"};
console.log(foo.n);
})(foo);
console.log(foo.n);
var foo = { n: 1};(function(foo) {// 这里是变量提升, 不懂的话现在记住了.// 我查阅了文档, 一个函数的形参的声明是优先于内部代码中的变量声明之前的, 所以这一行相当于无效.var foo;// 这里理所应当是 "1"console.log(foo.n);// 首先, 局部变量优先于外部变量所以这里是形参声明的 foo, 没疑问吧 ?// 我查阅文档说明: 形参实际上是一个新声明的变量, 赋值为实参也就是外面的 foo// 但是在 javascript 中将对象赋值给变量, 这个变量其实是个引用, 引用就是个地址, 赋值给形参中的 foo 时// 其实也就是让形参 foo 也指向对象 { n: 1}. 此时 foo.n = 3 将直接修改这个// 外部的 foo 指向的对象 (也是内部的 foo 此时指向的对象)foo.n = 3;// 这里前面也提到了. 形参中的 foo 其实是一个已经隐含声明的变量, 且 inner 的优先级高于 outer// 所以此时就是将形参指向另一个对象 { n: 2 };foo = { n: 2 };// inner 高于 outer, 所以读取的是形参的值 "2"console.log(foo.n);}(foo));// 之前在函数中被引用改变了, foo.n = 3. 所以此时结果为 "3"console.log(foo.n);
var x=1;
(function(x){
console.log(x)//1
var x=2
console.log(x)//2
})(x)
var x=1;
(function(x){
console.log(x)//undefined
var x=2
console.log(x)//2
})()
// 注意变量和对象属性的区别。 // 两种截然不同的情况,考的都是变量提升,也类似。 var foo = {n: 1}; (function (foo) { console.log(foo.n); // 1 foo.n = 3; var foo = {n: 2}; console.log(foo.n); // 2 })(foo); console.log(foo.n); // 3 var n = 1; (function (foo) { console.log(n); // undefined n = 3; var n = 2; console.log(n); // 2 })(foo); console.log(n); // 1
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(){ var foo // 声明形参 var foo // 变量提升,块内foo提升,此时后声明的覆盖前声明的 内部foo=外部foo //调用时传入的参数外部foo的引用,赋值给内部foo console.log(foo.n); // 输出foo.n 实际是输出外部foo的n 也就是1 foo.n = 3; // 此时修改foo.n 按照引用的规则 其实是修改外部 foo的n 此时外部的foo={n:3} foo = {n:2}; // 此时为内部foo重新赋值 新的引用地址,指向{n:2} console.log(foo.n); // 此时输出foo.n 指向新引用地址 也就是 foo={n:2} })(foo); console.log(foo.n); //此处直接调用外部foo.n 它依然是3
var foo = {n:1}; (function(foo){ console.log(foo.n);//输出形参foo中n的值1 foo.n = 3;//将形参foo中n的值改为3,此时全局中的foo对象也被修改 var foo = {n:2};//为局部变量foo赋值 console.log(foo.n);//输出局部变量foo中n的值2 })(foo); console.log(foo.n);//输出全局中foo对象的n值3
A