1. this是什么
this这个单词是一个代词,所以this应当是 指代某些东西
搞清晰this的症结的地方,就是要搞清晰this指代了什么
那末this究竟指代了什么呢?
就像你日常平凡
指着一个苹果说 this is an apple
指着一个香蕉说 this is a banana
一样,this也会由于状况的差别而差别
在JavaScript中
根据通例邃晓,this的值是什么取决于函数怎样被挪用
但是,this的值是什么完整取决于对应函数被call时传入的第一个参数,而这平常是由js提早就预置好的
2. 函数怎样被挪用
2.1 通例邃晓
注重:这类要领能够揣摸平常状况下的this是什么
- 揣摸this值就看函数是怎样被挪用的[函数有全局挪用和要领挪用]
- this指向挪用它的间隔近来的那一个
// 例子
function fn() {
console.log(this)
}
let obj = {
a: '',
fn: fn
}
// 场景一
fn() // window[浏览器] or global[node]
// 场景二
obj.fn() // obj
// 场景一:全局挪用
// 场景二:要领挪用
function VS method
- function xx(){…} 是function
- method某个对象下面的要领 如 obj = {fn:function(){…}} obj.fn() 叫做要领[method]
更细致的申明请看
深入浅出面向对象和原型【观点篇1】
// test1
function fn() {
console.log(this)
}
let obj1 = {
wrapper: {
a: 'a',
fn: fn
}
}
obj1.wrapper.fn() // ?
// fn()是被当作wrapper的要领被挪用的,所以this是wrapper
// this指向挪用它的间隔近来的那一个
// test2
function executeCallback(cb) {
cb()
}
executeCallback(obj1.wrapper.fn)
// this是全局变量
// 由于executeCallback函数是把cb当做全局函数举行挪用的
// 不像是obj.cb(),假如obj.cb()就是要领挪用了
根据通例邃晓已能够处理大部分的口试、笔试题了,但假如想究this之基础,还需要经由过程call
2.2 用call邃晓
注重:经由过程对call的开端邃晓,你能够晓得this的值为何是如许的,但这类头脑不方便你猜this
起首,我们要清晰this在函数中的位置
function fn1([this], parameter) {
// this就是隐蔽的第一个参数,而且永远是第一个参数
console.log(this)
}
其次,我们要晓得call的语法
fun.call(thisArg, arg1, arg2, ...)
OK,如今我们要晓得你在运用call的时刻
call传入的第一个参数能够指定(转变)fn1的第一个参数,也就是隐蔽的this
所以,为何直接全局挪用fn1时,打印出来的是window呢?
由于js已帮你call了
// 你写的代码
fn1()
// 在你写上面代码的时刻,js帮你写了一行你看不到的代码
fn1().call(undefined)
// 你能够回问:如许打出来的值应当是undefined呀
// 但浏览器有个机制
// 假如你传的 thisArg 就 null 或许 undefined,那末 window 对象就是默许的 context(严厉形式下默许 context 是 undefined)
我们从新来对待一下全局挪用和要领挪用,以及js是怎样用call指定this的
// 例子
function fn() {
console.log(this)
}
let obj = {
a: '',
fn: fn
}
// 场景一
fn() // window[浏览器] or global[node]
// js帮你写的代码
fn().call(undefined)
// 场景二
obj.fn() // obj
// js帮你写的代码
obj.fn().call(obj)
小测试(小圈套)
let module = {
x: 42,
getX: function () {
return this.x;
}
}
let retrieveX = module.getX;
console.log(retrieveX()); // undefined
console.log(module.getX()) // 42
2.3 严厉形式下的this
严厉形式下只需要
注重一点就行,别的状况下与非严厉形式雷同
全局作用域里函数中的this是undefined
function test() {
"use strict"
console.log(this)
}
test() // undefined
所以,在运用组织函数时,假如忘了加new,this不再指向全局对象,而是报错
,由于这就是函数的全局挪用
let People = function (name) {
"use strict"
this.name = name
}
People() // Cannot set property 'name' of undefined
3.几种庞杂状况中的this
3.1 数组中的this
function fn() {
console.log(this)
}
arr[fn, fn2, fn3]
arr[0]() // ??
// answer:arr
// 剖析
// 数组也是对象的一种
// arr[0]() 能够看作 arr.0().call(arr)
3.2 嵌套函数中的this
// 例子一
function fn0() {
function fn() {
console.log(this);
}
fn();
}
fn0(); // fn中this是全局变量
// 例子二
let a = {
b: function () {
console.log(this) // {b:fn}
function xx() {
console.log(this) // window
}
xx()
}
}
a.b()
3.3 setTimeout、setInterval中的this
document.addEventListener('click', function (e) {
console.log(this);
setTimeout(function () {
console.log(this); // 这里的this是全局变量
}, 200);
}, false);
3.4 事宜中的this
document.querySelector('div').addEventListener('click',function (e) {
console.log(this) // <div></div>
})
// 事宜里的this指向的是触发事宜的DOM节点
3.5 运用new时的this
4.总结
假如几种庞杂状况下的this你看完了,你应当会有迷惑
为啥我邃晓了全局挪用和要领挪用,但this的值依然和我揣摸的不一样呢?
我说过了,this的值是call的第一个参数,js已给许多this举行call了
所以,总结一下
- this的值是什么,你别猜,很能够会和你想的不一样
- console出来或许去看文档、看源码才是最稳妥的挑选
- 假如你非要猜,就套用一下我这篇博客写到的这几种状况
- 假如你怕猜错,又要用到this,很简单,直接用bind去强迫指定this
关于call/apply/bind 请看
this总结【2】—— call/apply和bind