this指向
在 ES5 中,this 永远指向最后调用它的那个对象
const o = { name:'global' }
const a = {
name: "active",
fn : function () {
console.log(this.name);
}
}
a.fn(); // active
箭头函数
箭头函数中没有this,箭头函数的this指向函数定义时的this,而非执行时。如果非箭头函数中包含箭头函数,则箭头函数内部的this则是非箭头函数的 this
const o = { name:'global' }
const a = {
name : "active",
func2: function () {
setTimeout( () => {
console.log(this.name);
},100);
}
}
a.func2() // active
call
如何使用
const o = { name:'global' }
const a = {
name: "active",
fn : function () {
console.log(this.name);
}
}
a.fn.call(o) // global
如何传参
const o = { name:'global' }
const a = {
name: "active",
fn : function (a,b) {
console.log(this.name,a,b);
}
}
a.fn.call(o,1,2) // global 1 2
如何实现
Function.prototype.call = function(context,...args){
context = context ? Object(context) : window // 将上下文设置成包装对象
args ||= []
const sym = Symbol()
context[sym] = this
const res = context[sym](...args) // this 永远指向最后调用它的那个对象 所以函数的this指向了context
delete context[sym]
return res
}
apply
如何使用
const o = { name:'global' }
const a = {
name: "active",
fn : function () {
console.log(this.name);
}
}
a.fn.apply(o) // global
如何传参
const o = { name:'global' }
const a = {
name: "active",
fn : function (a,b) {
console.log(this.name,a,b);
}
}
a.fn.apply(o,[1,2]) // global 1 2
如何实现
Function.prototype.apply = function(context,args){
context = context ? Object(context) : window
args ||= []
const sym = Symbol()
context[sym] = this
const res = context[sym](...args)
delete context[sym]
return res
}
call和apply区别
由上得:call 和 apply 使用上没区别,区别是传承方式不同。call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
思考:箭头函数能调用call吗
箭头函数也是函数,继承自Function,所以能调用call,但是不会改变其内部的this,因为箭头函数内部的this在其被定义的时候就确定了,不会改变。
bind
如何使用
bind执行后返回一个函数
const o = { name:'global' }
const a = {
name: "active",
fn : function () {
console.log(this.name);
}
}
const bindFn = a.fn.bind(o)
bindFn() // global
如何传参
const o = { name:'global' }
const a = {
name: "active",
fn : function (a,b) {
console.log(this.name,a,b);
}
}
// 这里两个函数执行都可以传参
const bindFn = a.fn.bind(o,1)
bindFn(2) // global 1 2
如何实现
Function.prototype.bind = function(context,args){
args ||= []
context = context ? Object(context) : window
const self = this
// return出去的函数是否被new 如果new 则内部的this指向实例
const resultFn = function (...args2) {
args2 ||= []
self.apply(
this instanceof resultFn ? this : context,
args.concat(args2))
}
// 继承构造函数上的方法
resultFn.prototype = Object.create(self.prototype)
return resultFn
}
思考:函数一直.bind结果如何?
const foo = function(){
console.log(this)
}
const bindFn = foo.bind(1).bind(2)
bindFn()
上面代码输出的this是什么呢? 从左到右先分析一波:
foo.bind(1)得到一个f1。 类似 f1 = function(){ foo.apply(1) }
foo.bind(1).bind(2) --> f1.bind(2)
得到一个f2 ,类似 f2 = function(){ f1.apply(2) }
这个f2就是上面的bindFn,然后bingFn执行,可以看到不管套了多少层,foo这个函数还是由foo.apply(1)执行,所以其内部的this还是1。都是第一次bind的对象!