【Javascript基础】一网打尽this, 对执行上下文说this - 实例分析说明

严格模式,非严格模式下

在函数体中,非显示或隐式地简单调用函数时,在严格模式下,函数内的this会被绑定到undefined上,在非严格模式下则会绑定到全局对象window/global上。

function f1() {
    console.log(this);
} 

function f2(){
    'use strict'
     console.log(this);
} 
f1();  // window
f2(); // undefined

对于下面这道题的运行结果:

const foo = {
    bar: 10,
    fn: function() {
         console.log(this);
         console.log(this.bar);
   }
}

var fn1 = foo.fn;
const foo = {
    bar: 10,
    fn: function() {
         console.log(this);
         console.log(this.bar);
   }
}

var fn1 = foo.fn;
fn1(); // window undefined

还是上面这道题目,如果将调用改为以下形式,

const foo = {
    bar: 10,
    fn: function() {
         console.log(this);
         console.log(this.bar);
   }
}

foo.fn();

则输出以下结果:
{bar: 10, fn: f}
10

构造函数中的this指向

一般使用new 方法调用构造函数时,构造函数内的this会绑定到新创建的对象上。

function Foo() {
    this.bar = 'Lucas';
}
const instance = new Foo();
console.log(instance.bar); // Lucas

call, apply, bind函数体内this指向

一般通过call/apply/bind方法显示调用函数时,函数体内的this会被绑定到指定参数的对象上。

// 1
const target = [];
fn.call(target, 'arg1', 'arg2');

// 2
const target = [];
fn.apply(target, ['arg1', 'arg2']);

// 3
const target = [];
fn.bind(target, 'arg1', 'arg2');

call和apply时直接进行相关函数调用的,bind不会执行相关函数。

上下文中this指向

一般通过上下文对象调用函数时,函数体内的this会被绑定到该对象上。

const o1 = {
   text: 'o1',
   fn: function() {
       return this.text;
   }
}

const o2 = {
    text: 'o2',
    fn: function() {
        return o1.fn();
    }
}

const o3 = {
    text: 'o3',
    fn: function() {
        var fn = o1.fn;
        return fn();
   }
}

console.log(o1.fn()); // o1
console.log(o2.fn()); // o1
console.log(o3.fn()); //undefined

this也有一定的优先级,一般来说,call, apply的显式绑定优先级更高,new绑定的优先级比显式bind绑定的更高。

箭头函数this指向

在箭头函数种,this的指向是由外层(函数或全局)作用域来决定的。

const foo = {
    fn: function() {
        setTimeout(function() {
            console.log(this); // this指向window
        })
    }
}

const foo = {
    fn: function() {
        setTimeout(() => {
            console.log(this); // this指向foo对象
        })
    }
}

实现一个bind函数

Function.prototype.bind = Function.prototype.bind || function (context) {
    var me = this;
    var args = Array.prototype.slice.call(arguments, 1);
    return function bound() {
       var innerArgs = Array.prototype.slice.call(arguments);
       var finalArgs = args.concat(innerArgs);
       return me.apply(context, finalArgs);
   }
}

变量作用域

let a = 10;
function a1() {
    let a = 20;
    a2();
}

function a2() {
    console.log(a);
}

a1();

以上的结果是 10。因为a2函数在调用的时候,把a2函数提升了,这时候a变量是全局的a, 也就是作用域是window。

换个方式:把a2写到函数a1里面,结果就会是20.

let a = 10;
function a1() {
    let a = 20;
    function a2() {
        console.log(a);
    }

    a2();
}

a1();
posted @ 2021-03-01 23:14  攀登高山  阅读(35)  评论(0编辑  收藏  举报