this: 当前执行上下文(global、function、eval)的一个属性,在非严格模式下总是指向一个对象;在严格模式下可以为任意值。
全局上下文环境:
在全局执行环境(在任何函数体外部)中,无论是否为严格模式,this都指向全局对象(在浏览器中全局对象为window;在Node环境中全局对象为globalThis);
函数上下文环境:
在函数内容,this的值取决于函数被调用的方式。
在非严格模式下,直接调用f1函数,此时this的指向为全局对象,因为在浏览器中直接调用f1函数,相当于 window.f1();
在严格模式下直接调用f2函数,此时this的值为undefined,因为在直接调用f2函数进入f2函数执行环境时没有设置this的值;
类上下文环境:
this在类中的表现与函数中相似,需注意的是:在类的构造函数中,this是一个常规对象;类中所有非静态方法都会被添加到this的原型中。
在非严格模式下使用call()和apply()时,如果指定this的值(即call和apply方法中的第一个参数)不是对象,则会被尝试的转化为对象(如:7 --> New Number(7)),null 和 undefined 会被转化为全局对象。
call() 和 apply() 方法的区别:call()方法传参数时直接写值,apply()方法传参数时需以数组的形式传递
箭头函数中的this
在箭头函数中,this与封闭词法环境中的this保持一致,不再取决于函数被调用时的环境,而是取决于箭头函数被创建时的环境.
箭头函数中的this会被永久绑定到它外层函数的this。
当函数作为对象里的方法被调用时,this 被设置为调用该函数的对象,且 this 的绑定只受最接近的成员引用的影响
当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象
function f1() { console.log(this); } f1(); // Window -- 浏览器中,相当于 window.f1(); globalThis -- Node中 function f2() { 'use strict'; // 采用严格模式 console.log(this); } console.log('直接调用f2'); f2(); // undefined console.log('采用window.f2()'); window.f2(); // Window console.log('===================================='); var obj = {a: 'Custom'}; var a = 'Global'; function whatsThis() { return this.a; } console.log(whatsThis()); // Global console.log(whatsThis.call(obj)); // Custom console.log(whatsThis.apply(obj)); // Custom console.log('===================================='); function add(c, d) { return this.a + this.b + c + d; } var o = {a: 1, b: 3}; console.log(add.call(o, 5, 7)); // 1+3+5+7 = 16 console.log(add.apply(o, [10, 20])); // 1+3+10+20 = 34 console.log('===================================='); function f(){ return this.a; } var g = f.bind({a:"azerty"}); // 变量 g 为一个函数,方法体内容同函数 f 一致,this被永久指向{a:"azerty"}对象 console.log(g()); // azerty var h = g.bind({a:'yoo'}); // 变量 h 为一个函数,方法体内容同函数 g 一致 console.log(h()); // azerty -- bind只生效一次! var o = {a:37, f:f, g:g, h:h}; console.log(o.a, o.f(), o.g(), o.h()); // 37, 37, azerty, azerty console.log('===================================='); var globalObject = this; var foo = (() => this); console.log(foo() === globalObject); // true var obj = {foo: foo}; console.log(obj.foo() === globalObject); // true console.log(foo.call(obj) === globalObject); // true foo = foo.bind(obj); console.log(foo() === globalObject); // true console.log('===================================='); var obj = { bar: function() { var x = (() => this); return x; } }; var fn = obj.bar(); // fn 为箭头函数(() => this) console.log(fn() === obj); // true var fn2 = obj.bar; // fn2 为函数function() {var x = (() => this); return x;} console.log(fn2()() == window); // true console.log('===================================='); var o = { a: 10, b: 20, f: function() { return this.a + this.b; } }; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5 console.log('===================================='); function sum() { return this.a + this.b + this.c; } var o = { a: 1, b: 2, c: 3, get average() { return (this.a + this.b + this.c) / 3; } }; Object.defineProperty(o, 'sum', { get: sum, enumerable: true, configurable: true}); console.log(o.average, o.sum); // 2, 6