【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();