this

一. this是什么

  • 隐藏参数
  • 声明函数时附加的参数,指向调用它的对象

二. this指向

  • this的指向在函数创建时是决定不了的, 在最后调用的时候才可以决定,谁调用就指向谁

三. this使用的几种情况

1. 普通函数调用(默认绑定) —> 指向window
//直接打印
console.log(this) //window

//function声明函数
function bar () {console.log(this)}
bar() //window

//function声明函数赋给变量
var bar = function () {console.log(this)}
bar() //window

//自执行函数
(function () {console.log(this)})(); //window
2. 对象函数调用(隐式绑定) —> 指向最后调用的对象
//对象方法调用
var person = {
  run: function () {console.log(this)}
}
person.run() // person

window.b=2222
let obj={
    a:111,
    fn:function(){
        alert(this.a);//111 this指向obj
        alert(this.b);//undefined this指向obj,obj没有b属性
    }
}
obj.fn();
2.1隐式绑定丢失问题
  • 使用另一个变量给函数取别名

    function foo () {
      console.log(this.a)
    };
    var obj = { a: 1, foo };
    var a = 2;
    var foo2 = obj.foo;
    
    obj.foo();
    foo2();
    
    
  • 把函数当做参数传递给其他函数,回调函数会丢失this指向

    • 注意:还要区分是否为严格模式
    • 严格模式 :会把this绑定到undefined
    • 非严格模式 :会把this绑定到window
    "use strict"
    function foo () {
      console.log(this.a)
    }
    function doFoo (fn) {
      console.log(this)
      fn()
    }
    var obj = { a: 1, foo }
    var a = 2
    var obj2 = { a: 3, doFoo }
    
    obj2.doFoo(obj.foo)
    
3. 构造函数绑定 (new)—> 指向根据是否有实例化去判断
//不使用new指向window
function Person(name) {
  console.log(this) // window
  this.name = name;
}
Person('inwe')
//使用new
function Person(name) {
  this.name = name
  console.log(this) //people
  self = this
}
var people = new Person('iwen')
console.log(self === people) //true
//这里new改变了this指向,将this由window指向Person的实例对象people
4. 箭头函数绑定 —> 指向window
  • 箭头函数里面的 this 是继承外面的环境
  • 向上层作用域查找
  • 箭头函数的this是无法通过bind、call、apply来直接修改,但是可以通过改变作用域中this的指向来间接修改
  • 字面量创建的对象,作用域是window,如果里面有箭头函数属性的话,this指向的是window
  • 构造函数创建的对象,作用域是可以理解为是这个构造函数,且这个构造函数的this是指向新建的对象的,因此this指向这个对象
  • 非箭头函数查找顺序:
    • obj -> fn -> seTimeout -> 普通函数
    • window <- 普通函数
  • 箭头函数:
    • obj -> fn -> seTimeout -> 箭头函数
    • obj <- fn <- seTimeout <- 箭头函数
    let obj={
        a:222,
        fn:function(){    
        	//1.不使用箭头函数
        	//setTimeout(function(){
        		console.log(this.a)
        	})
        	//2.使用箭头函数
            setTimeout(()=>{
            	console.log(this.a)
            })
        }
    };
    //1.不使用箭头函数的结果
    //obj.fn();//undefined
    obj.fn();//222
    
5. 函数调用,call、apply传入的参数改变this指向(显式绑定)—> 根据参数决定指向
  • call :
    • 第一个参数决定函数体内 this 的指向,第二个参数以下是依次传入的参数;
    • 在一个函数内使用call来显式绑定某个对象,这样无论怎样调用它,其内部的this总是指向这个对象
    function foo1 () {
      console.log(this.a)
    }
    var a = 1
    var obj = {
      a: 2
    }
    
    var foo2 = function () {
      foo1.call(obj)
    }
    
    foo2()
    foo2.call(window)
    
  • apply : 第一个参数决定函数体内 this 的指向,第二个参数是一个集合对象(数组或者类数组)
  • bind :创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
  • 注意:foo.call()和foo().call()的区别
    • 前者针对函数,后者针对函数的返回值
    let fn=function(a,b,c){
    console.log(a,b,c);
    }
    let arr=[1,2,3];
    fn.call(window,arr);
    fn.apply(window,arr);
    fn.bind(window,arr)();
    
6.“use strict” 严格模式
  • 使用了"use strict"开启严格模式会使得"use strict"以下代码的this为undefined

四、变态题

1.显示绑定练习题

原文链接练习题原文链接: https://juejin.im/post/5e6358256fb9a07cd80f2e70#heading-15.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值