({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
({
x: 10,
foo: function () {
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
var x = 20;
var y = 30;
bar.call(this);
}
}
}).foo();
等价转换为==>
var obj={
x: 10,
foo: function () {
var x,y;
function bar() {
console.log(x);//1
console.log(y);//2
console.log(this.x);//3
}
with (this) {//4
x = 20;//5
y = 30;//6
bar.call(this);//7
}
console.log(x);//8
x=999;
console.log(x);//9
}
};
obj.foo();//10
with语句中的变量x,y声明提前到函数顶部;
with关键字会将with对应的对象添加到当前其所在函数作用域链的头部位置,也就是with语句块中的属性首先从头部位置的对象开始找,找不到再往上...等with语句执行完后,会恢复原来你的函数作用域链。
对于以上的问题:obj.foo();
执行,[4]处的this为obj对象,[5]x=20;
obj有x属性,故obj.x属性值被更新为20,foo
函数体的x变量值没有被赋值;[6]y=30;
obj没有y属性,故foo
函数体中的变量赋值为30;bar.call(this);
执行时,obj的属性x值为20,
[1]输出为undefined
[2]输出为30
[3]输出为20
[8]输出为undefined
[9]输出为999
({
x: 10,
foo: function () {
var x, y
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
this.x = 20;
y = 30;
bar.call(this);
}
}
}).foo();
不要用with,也不用去学 何乐而不为
作用域链的顶部添加with传入的对象,即:with内先查找和操作该对象的属性,如果该对象没有找到,再往作用域链的下一级查找,然后操作操作。(obj作用域——>函数1——>函数2——>...——>window全局作用域)
问题中,变量声明提示和函数声明提升后的实际代码是:
({
x: 10,
foo: function () {
var x;//默认undefined,等会分析要用到
var y;//默认undefined
function bar() {
console.log(x);
console.log(y);
console.log(this.x);
}
with (this) {
x = 20;
y = 30;
bar.call(this);
}
}
}).foo();
var x; x变量的默认值undefined;
var y;y变量的默认值undefined;
等会分析会用到
当代码走到with中时,this是外面的大对象。
(1)x =20
根据with的特点(上面提到的),先在this大对象中找x属性(对象中叫属性,函数叫变量),巧了,this大对象有x:10,将值改为20;
(2)y =30
同样的,在this大对象中找y属性,没有!再去foo函数中y变量,有!设置y为30;
(3)bar.call(this)
大家要注意:call apply bind(ES5)都是只改变this指向,this指向只与this对象相关的操作有关。与函数变量没有一点关系!!!
执行bar函数,call修改this指向,指向大对象。
bar函数执行
(1)打印变量x。bar函数中没有变量x,往上面的作用域找,foo函数中有变量x,x的值是undefined。(with改变的x是指大对象的x属性)
(2)打印变量y。bar函数没有变量y,往上找,foo函数中有变量y,值为30。(with语句改变y的时候,先去大对象中找y属性,没有,再去foo函数中找到y变量,并将其修改为30)
(3)打印this.x。打印大对象的x属性,值为20。
变量x:undefined
变量y:30
this.x:20
13 回答13.1k 阅读
7 回答2.3k 阅读
3 回答1.4k 阅读✓ 已解决
6 回答1.5k 阅读✓ 已解决
2 回答1.5k 阅读✓ 已解决
3 回答1.5k 阅读✓ 已解决
2 回答1.2k 阅读✓ 已解决