this、JS的作用域及作用域链

一.什么是作用域呢?

在 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

猜你喜欢

转载自blog.csdn.net/huihui_999/article/details/131511576