美文网首页
this详解

this详解

作者: YQY_苑 | 来源:发表于2017-12-08 15:42 被阅读0次

当我们执行一个函数,以下几种调用方式等价

"use strict"
function fn(a,b){
    console.log(this)
}
fn(1, 2)

//等价于
fn.call(undefined, 1, 2)
fn.apply(undefined, [1, 2])
  • 在严格模式下, fn 里的 this 就是 call 的第一个参数,也就是 undefined。
  • 在非严格模式下(不加"use strict"), call 传递的第一个参数如果是 undefined 或者 null, 那 this 会自动替换为 Window 对象
var obj = {
    fn: function(a, b){
        console.log(this)
    },
    child: {
        fn2: function(){
            console.log(this)
        }
    }
}
obj.fn(1, 2)

//等价于
obj.fn.call(obj, 1, 2)         // 所以 this 是 obj
obj.fn.apply(obj, [1, 2])

obj.child.fn2()
//等价于
obj.child.fn2.call(obj.chid)    // 所以 this 是 obj.child

测试题

let name = 'YQY'
let people = {
    name: '若愚',
    sayName: function(){
        console.log(this.name)
    }
}
let sayAgain = people.sayName
function sayName(){
    console.log(this.name)
}

sayName()
/*
 解析:相当于 `sayName.call(undefined)` ,因为是非严格模式,
所以 this 被替换成 Window,所以这里输出全局的 name 即 "YQY"
*/

people.sayName()
/*
解析: 相当于 `people.sayName.call(people)` ,所以这里输出 `people.name` 即 "若愚"
*/

sayAgain()
/*
解析: 相当于 `sayAgain.call(undefined)` ,因为是非严格模式,
所以 this 被替换成 Window,所以这里输出全局的 name 即 "YQY"
*/

var arr = []
for(var i=0; i<3; i++){
    arr[i] = function(){ console.log(this) }
}
var fn = arr[0]

arr[0]
/*
解析: 因为函数是个特殊的对象,
所以 arr 相当于 { '0': function(){}, '1': function(){}, '2': function(){}, length:3}

arr[0]相当于 `arr['0']` 相当于 `arr.0` (当然这种写法不符合规范),
所以 arr[0]等价于 arr.0.call(arr), this就是 arr
*/

fn()
/*
解析: 相当于 `fn.call(undefined)`, 所以 fn 里面的 this 是 Window
*/

bind

  • bind 的作用和 call 与 apply 类似,区别在于使用上
  • bind 的执行的结果返回的是绑定了一个对象的新函数
var obj = {name: 'YQY'}
function sayName(){
    console.log(this.name)
}
var fn = sayName.bind(obj) 
 // 注意 这里 fn 还是一个函数,功能和 sayName 一模一样,区别只在于它里面的 this 是 obj

fn() // 输出: 'YQY'
  • 一个实际点的例子
var app = {
    container: document.querySelector('body'),
    bind: function(){
        this.container.addEventListener('click', this.sayHello)                 
        //点击的时候会执行 sayHello,sayHello 里面的 this 代表 body 对象

        this.container.addEventListener('click', this.sayHello.bind(this)) 
       //点击的时候会执行 sayHello,sayHello 里面的 this 代表 app 对象
    },
    sayHello: function(){
       console.log(this)
    }
}
app.bind()

箭头函数

如果你经常用 ES6语法,你会发现关于函数这两种写法

let app = {
    fn1: function(a){
        console.log(this)  //app
    }
    fn2(a) {
        consoel.log(this)  //app
    },
    fn3: (a)=>{
        console.log(this)  //window
    }
}
  • 粗略一看,fn1、fn2、fn3 貌似都一样,实际上 fn1和 fn2完全等价,但 fn3是有区别的
    以上代码等同于
app.fn2.call(app)
app.fn3.call( 它的上一级的 this )
  • 再给个复杂点的例子就清楚了
var app = {
    init() {
        var menu = {
            init: ()=>{
                console.log(this)
            },
            bind() {
                console.log(this)   
            }
        }
        menu.init() 
         /*相当于  menu.init.call(menu 所在的环境下的 this)  , 
                所以 init 里面的 this 也就是 app。
         (假设 app.init 也是箭头函数,想想 menu.init 里面的 this 是什么?)          
         */
        menu.bind() 
        /*相当于 menu.bind.call(menu),也就是 menu,所以 bind 里面的 this 就是 menu
        */
    }
}
app.init()
  • 理解后完成如下题目
var app = {
    fn1() {
        setTimeout(function(){
            console.log(this)
        }, 10)
    },
    fn2() {
        setTimeout(()=>{
            console.log(this)
        },20)
    },
    fn3() {
        setTimeout((function(){
            console.log(this)
        }).bind(this), 30)        
    },
    fn4: ()=> {
        setTimeout(()=>{
            console.log(this)
        },40)        
    }
}
app.fn1()
app.fn2()
app.fn3()
app.fn4()

以上代码相当于

var app = {
    fn1() {
        function fn(){
            console.log(this)
        }
        //过10ms 后执行
        //fn.call(undefined) ,所以输出 Window
    },
    fn2() {
        //过20ms 执行箭头函数
        //箭头函数里面没资格有 自己的 this,借用 setTimeout 外面的 this,也就是 app
    },
    fn3() {
        // 创建了一个新函数,这个新函数里面绑定了 外面的this,也就是 app
        // 20 ms 后执行新函数,输出 this,也就是刚刚绑定的 app    
    }
    fn4: ()=> {
        //过40ms 执行箭头函数
        //箭头函数里面没资格有 this,用 setTimeout 外面的 this
        //setTimeout 所在的 fn4也是箭头函数,没资格拥有自己的 this,
               借用外面的 this ,也就是 Window     
    }
}

相关文章

网友评论

      本文标题:this详解

      本文链接:https://www.haomeiwen.com/subject/jlbeixtx.html