在javascript中this出现的频率很高,我们总是能看见var serlf = this 或者 var _this = this之类的操作。那么到底this是什么? 先抛个答案:函数的上下文context,this完全取决于函数的调用位置。 常见的错误看法有1)this指向函数本身;2)this指向函数的词法作用域
为何要用this
this可以用来隐式传参
function identify(){
return this.name.toUpperCase()
}
function speak(){
var greeting = "Hello, I'm " + identify.call(this)
console.log(greeting)
}
var me ={
name:"Kyle"
}
var you ={
name:"Reader"
}
identify.call(me)//KYLE
speak.call(you)//Hello, 我是KYLE
//如果不用this
function identify(context){
return context.name.toUpperCase()
}
function speak(context){
var greeting = "Hello, I'm " + identify.call(context)
console.log(greeting)
}
identify(you)//READER
speak(me)//Hello, I'm KYLE
this的规则
- 对于直接调用不带任何修饰的函数进行调用,那么其this指向全局对象,在浏览器中为window,Nodejs中为global(PS:1)其实也相当于window.fn();2)在一个函数内部直接调用另一个函数,那么另一个函数的this也是指向全局)
- 隐式绑定:在对象内部使用函数,那么函数的this指向这个对象,此时,函数也被成为方法;值得注意的是当函数作为回调函数传入的时候this会丢失,导致函数产生错误,因为才有了开头var that = this这种写法
//隐式丢失
function foo(){
console.log(this.a)
}
var obj ={
a:2,
foo
}
var bar = obj.foo
bar()//报错 找不到a
- 硬绑定:1)bind,apply,call方法;2)某些函数如forEach()可以传入obj作为参数来实现硬绑定
- new绑定
function new(constructor){
//1.创建一个新对象
const obj ={}
//2.将新对象的原型与构造函数的原型链接
obj.prototype = constructor.prototype
//3.构造函数在新对象内部运行
const res = constructor.apply(obj,arguments)
//4.如果构造函数的运行结果是对象就返回该对象,否则返回obj
return (res instanceof Object) ? res : obj
}
绑定级别
new > bind/apply/call > 隐式 > 直接调用
//bind实现
Function.prototype.myBind(){
const that = this
const obj = arguments[0]
const args = [].slice.call(arguments).slice(1)
return function Fn(){
//判定是否执行了new操作
//在执行new操作的时候,Fn运行在对象的内部,this就为新对象,
//如果new成功了,那么新对象就是返回的Fn函数的实例
if(this instanceof Fn){
return new that(...args, ...arguments)
}else{
return that.apply(obj, args.concat([].slice.call(arguments))
}
}
}
//apply实现
Function.prototype.myApply(){
const obj = arguments[0]
const args = arguments[1]
obj.fn = this
let result
if(args.length>0){
result = obj.fn(...args)
}else{
result = obj.fn()
}
delete obj.fn
return result
}
//call实现
Function.prototype.myCall(){
const obj = arguments[0]
const args = Array.from(arguments).slice(1)
obj.fn = this
const result = obj.fn(...args)
delete obj.fn
return result
}
箭头函数
- this完全指向词法作用域,因此经常将箭头函数作为回调函数传入,防止this丢失;另外在原型脸上定义函数的时候不要使用箭头函数,否则会丢失对象;bind,call,apply不能改变其作用域
- 不可以用作构造函数
- 不可以使用arguments对象,但是可以用rest参数
cosnt fun = (...args) =>{
console.log(args)
}
fn(1,2,3) //[1,2,3]
- 不可以使用yiled命令,因此不能作为生成器函数