什么是this
this不是编写时绑定,是运行时绑定。即没调用函数之前无法确定this指向。
注意
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象
this指向例子
例子1:
test() 相当于window.test()调用 即this指向
window
注意: 当 开启严格模式
this
指向undefined
function test() {
console.log(this.user)
console.log(this)
}
test() // undefined window
2
3
4
5
6
例子2:
对象obj在创建之初,this的指向无法确定。
当
fn
通过obj.fn
调用之时,根据执行上下文确定了this
指向为obj
谁调用的就指向谁
const obj = {
user: '说不准的',
fn() {
// 此时无法确定this 只有当调用之时才能确定
console.log(this.user)
}
}
obj.fn() // 说不准的
2
3
4
5
6
7
8
例子3:
例子2的时候说
谁调用指向谁
,这里需要完善一下。有以下三种情况1: 如果函数有this,但此函数没有被上级对象调用,那么此this指向window(严格模式下指向undefined)
2: 如果函数有this,这个函数有被上级对象调用,那么此this指向此对象
3: 如果函数有this,这个函数包含多个对象,this也只是指向上层对象,而非最外层对象。
const obj = {
a: 10,
b: {
a:12,
fn() {
console.log(this.a)
}
}
}
obj.b.fn() // 12
2
3
4
5
6
7
8
9
10
例子4:
与例子3 稍微改动下,重新申明个变量接受函数 fn,再执行
结果却是
undefined
始终注意这一点,this是谁调用就指向谁,尽管fn被obj.b 包裹,但是调用之时是 window.fn调用,所以指向window
const obj = {
a: 10,
b: {
a:12,
fn() {
console.log(this.a)
}
}
}
const fn = obj.b.fn
fn() // undefined
2
3
4
5
6
7
8
9
10
11
例子5:
构造函数 this指向
由于是new运算符改变内部this指向
function Fn() {
console.log(this)
}
const fn = new Fn() // Fn
2
3
4
改变this指向
javascript中bind,call,apply改变this指向
注意
1:箭头函数 无法改变this指向 (在哪定义就继承上级执行上下文this)
2:bind 返回一个更改this之后的函数
3:call 第一个参数为this指向,后续为参数化 obj.fn.call({}, 1, 2)
4:apply 第一个参数为this指向,后续为参数类数组 obj.fn.apply({}, [1, 2])
call 实现
改变this指向原理是 谁调用,this指向谁
Function.prototype.myCall = function(ctx, ...args) {
ctx = ctx || window
if (typeof ctx !== 'object') {
ctx = new Object(ctx)
}
ctx.fn = this
const result = ctx.fn(...args)
delete ctx.fn
return result
}
2
3
4
5
6
7
8
9
10
11
12
13
14
apply 实现
Function.prototype.myApply = function(ctx, ...args) {
ctx = ctx || window
if (typeof ctx !== 'object') {
ctx = new Object(ctx)
}
ctx.fn = this
const result = args.length ? ctx.fn(...args[0]) : ctx.fn()
delete ctx.fn
return result
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bind 实现
Function.prototype.myBind = function(ctx, ...args) {
ctx = ctx || window
if (typeof ctx !== 'object') {
ctx = new Object(ctx)
}
ctx.fn = this
return function() {
const result = ctx.fn(...args, ...arguments)
delete ctx.fn
return result
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15