JavaScript this 关键字
this
是 JavaScript 的一个关键字,一般指向调用它的对象
- 首先
this
指向的应该是一个对象,更具体的说是函数执行的上下文 - 如果调用它的不是对象或者对象不存在默认指向全局对象,严格模式下为 ``undefined`
let a = {
a1: 'a1',
fn() {
console.log(this.a1)
}
}
a.fn() // a1
class B {
b1 = 'b1'
fn() {
console.log(this.b1)
}
}
let b = new B()
b.b1 = 'b2'
b.fn() // b2
// window.c = 'c' 浏览器
globalThis.c = 'c' // node
function fn() {
console.log(this.c)
}
fn() // c
function fn () {
console.log(this)
}
function fn2() {
fn()
}
fn2() // global/window
class B {
fn() {
console.log(this)
}
}
let b = new B()
let func = b.fn
func() // undefined
/*
是因为类的内部采用严格模式,即
class B {
'use strict';
fn() {
console.log(this)
}
}
*/
function fn () {
console.log(this)
}
function fn2() {
fn()
}
let obj = {
fn2
}
obj.fn2() // 内部的 fn 的 this 还是指向 global/window fn2 不会将自己的 this (obj)传递给 fn
let obj = {
arr: [1]
}
obj.arr.forEach(function() {
console.log(this) // global/window
})
// 打印 this 为 global/window 是因为在 forEach 源码中,定义了 T 用来接收 this, if (arguments.length > 1) { T = thisArg; } 如果没有,即为 undefined, call(undefined) 指向 global/window
// forEach 源码
if (!Array.prototype['forEach']) {
Array.prototype.forEach = function(callback, thisArg) {
if (this == null) { throw new TypeError('Array.prototype.forEach called on null or undefined'); }
var T, k;
// 1. Let O be the result of calling toObject() passing the
// |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get() internal
// method of O with the argument "length".
// 3. Let len be toUint32(lenValue).
var len = O.length >>> 0;
// 4. If isCallable(callback) is false, throw a TypeError exception.
// See: https://es5.github.com/#x9.11
if (typeof callback !== "function") { throw new TypeError(callback + ' is not a function'); }
// 5. If thisArg was supplied, let T be thisArg; else let
// T be undefined.
if (arguments.length > 1) { T = thisArg; }
// 6. Let k be 0
k = 0;
// 7. Repeat, while k < len
while (k < len) {
var kValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty
// internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal
// method of O with argument Pk.
kValue = O[k];
// ii. Call the Call internal method of callback with T as
// the this value and argument list containing kValue, k, and O.
callback.call(T, kValue, k, O);
}
// d. Increase k by 1.
k++;
}
// 8. return undefined
};
}
let obj = {
arr: [1]
}
// 如果是,箭头函数
module.exports.c='m'
globalThis.c = 'c'
// window.c = 'w'
obj.arr.forEach(() => {
console.log(this.c) // node: m, 浏览器: w
})
;(() => { // 加分号是为了防止,压缩 js 时,可能出现错误调用的情况,不加会报错
console.log(this.c) // node: m, 浏览器: w
})()
let test = { fn: () => console.log(this) }
test.fn() // { c: 'm' }(module.exports)/window
// 可以将 箭头函数作为属性在对象方法内调用,当调用对象方法时,this 便会通过 对象方法 指向对象
let test = {
fn() {
const f = () => console.log(this)
f()
}
}
test.fn() // test 对象
// node 模块引用
function require(modulePath){
//1、将 modulePath 转换为绝对路径
//2、判断是否该模块已有缓存 require.cache
//3、读取文件内容
//4、包裹到一个函数中
function __temp(module,exports,require,__dirname,__filename) {
//.....
}
//6.创建module对象
module.exports={};
const exports=module.exports;
//执行读取文件函数
// 执行 call, 将 module.exports 输入为模块的 this,箭头函数无指向,就会指向模块的 this,即 module.exports
__temp.call(module.exports,module,exports,require,module.path,module.filename)
//最终返回module.exports
return module.exports;
}
//定义缓存对象
require.cache={};
[0].forEach(function() {
console.log(this)
}, 0)
// [Number: 0]
改变this
function getName() {
console.log(this.name)
}
let n = getName.bind({name:'bind'}) // 绑定 this
n()
getName.call({name:'call'}) // 调用并设置 this, 传入参数
getName.apply({name:'apply'}) // 调用并设置 this, 传入参数数组