一.什么是作用域呢?
在 Javascript 中,作用域分为 全局作用域
和 函数作用域
-
全局作用域:代码在程序任何地方都能访问,window对象的内置属性都属于全局作用域
-
函数作用域:在固定的代码片段才能被访问
作用域有上下级关系,上下级关系的确定就看函数是在哪个作用域下创建的。如上,fn作用域下创建了bar函数,那么“fn作用域”就是“bar作用域”的上级。
作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
二.什么是作用域链?
一般情况下,变量取值到 创建 这个变量 的函数的作用域中取值
但是如果在当前作用域中没有查到值,就会向上级作用域去查,直到查到全局作用域,这么一个查找过程形成的链条就叫做作用域链。
var x = 10;
function fn(){
console.log(x);
}
function show(f){
var x = 20;
f(); // 10
}
show(fn);
三.this
this
关键字是函数运行时自动生成的一个内部对象,只能在函数内部使用,总指向调用它的对象.
1.例子1
function baz() {
// 当前调用栈是:baz
// 因此,当前调用位置是全局作用域
console.log("baz");
bar(); // <-- bar的调用位置
}
function bar() {
// 当前调用栈是:baz --> bar
// 因此,当前调用位置在baz中
console.log("bar");
foo(); // <-- foo的调用位置
}
function foo() {
// 当前调用栈是:baz --> bar --> foo
// 因此,当前调用位置在bar中
console.log("foo");
}
baz(); // <-- baz的调用位置
2.this
在函数执行过程中,this
一旦被确定了,就不可以再更改
var a = 10;
var obj = {
a: 20
}
function fn() {
this = obj; // 修改this,运行后会报错
console.log(this.a);
}
fn();
四.this绑定规则
(1)默认绑定(先排除严格模式)
var name = 'Jenny';
function person() {
return this.name;
}
console.log(person()); //Jenny
//调用函数的对象在游览器中位window,因此this指向window,所以输出Jenny
(2)隐式绑定--函数还可以作为某个对象的方法调用,这时this
就指这个上级对象
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m(); // 1
这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用,this
指向的也只是它上一级的对象。
var o = {
a: 10,
b: {
fn: function () {
console.log(this);// fn:ƒ()
console.log(this.a); //undefined
}
}
}
o.b.fn();
此时this
指向的是window
,需要记住的是,this
永远指向的是最后调用它的对象,虽然fn
是对象b
的方法,但是fn
赋值给j
时候并没有执行,所以最终指向window
(3)显式修改
apply()、call()、bind()
是函数的一个方法,作用是改变函数的调用对象。它的第一个参数就表示改变后的调用这个函数的对象。因此,这时this
指的就是这第一个参数。
var x = 0;
function test() {
console.log(this.x);
}
var obj = {};
obj.x = 1;
obj.m = test;
obj.m.apply(obj) // 1