this指向之js函数的四种调用模式

this的指向是动态的,只有在函数调用时才能够确定(跟函数的调用模式相关),函数申明时并不能确定this的指向

1函数调用
let function fn(){
	console.log(this)
}
fn()
//this->Window
2方法调用
let obj{
 	fn:function(){
		console.log(this)
	}
}
obj.fn()  //this->obj


let function fn(){
	console.log(this)
}
let obj{
 	fn:fn
}
obj.fn()
//this->obj
obj['fn']()
//this->obj

setTimeout是Window中的一个方法,
是Window.setTimeout(fn(),50)简写形式
所以this其实还是指向调用他的对象Window

 setTimeout(function () {
    console.log(this);//Window 
  }, 50);

事件中的this指向当前元素,浏览器让当前元素调用了function

3构造函数调用
function Person(name, age) {
    this.name = name
    this.age = age
  }

  let p = new Person('zs', 20)
  console.log(p); //Person {name: "zs", age: 20}
//this->Person的实例p
4借用(call,apply,bind)

call()的作用有两个,一是调用函数,二是更改函数的this指向

 function fn() {
    console.log(1);
    console.log(this);
  }
  let zs = {
    money: 10
  }
  fn.call() // 1 Window
  fn.call(zs) // 1 {money: 10}

call()的第一个参数设定this的指向,后面的参数为fn的实参

因为其更改this指向的特性,可以实现借用方法

let zs = {
    money: 10,
    liaomei: function () {
      console.log('走,哥有' + this.money + '块,我们去酒吧撩妹');
    }
  }
  let ls = {
    money: 1000
  }
  zs.liaomei() //走,哥有10块,我们去酒吧撩妹
  zs.liaomei.call(ls) //走,哥有1000块,我们去酒吧撩妹
  //借用之后ls还是没有liaomei方法

 function fn(m, n) {
    console.log(this);
    console.log(m + n);
  }
  fn(1, 2) // 3 Window
  fn.call({name: 'zs'}, 10, 20) // 30 {name: "zs"}
  fn.apply({name: 'ls'}, [100, 200]) // 300 {name: "zs"}
  //注意apply的第二个参数,必须是数组
  //apply使用场景较少,参数已经放在数组或伪数组里才使用

比如求数组最大值

  arr = [1, 2, 3, 4, 5, 6, 7]
  let res1 = Math.max(1, 2, 3, 4, 5, 6, 7)
  let res2 = Math.max(arr)
  let res3 = Math.max.apply(arr, arr)
  console.log(res1); // 7
  console.log(res2); // NaN  Math.max参数要求为一项一项的数值
  console.log(res3); // 7
  //借用max方法,第一个arr参数改变this指向借用,第二个arr参数apply展开平铺

bind方法仅改变函数的指向,并返回一个和原函数一模一样的函数,不调用函数(不常用)

let user = {
    uname: 'zs',
    pwd: '123456',
    login: function () {
      let fn = function () {
        console.log('用户' + this.uname + '的密码为' + this.pwd);
      }
      setInterval(fn, 1000); //fn中this的指向为Window
    }
  }
  user.login() // 用户undefined的密码为undefined

  let user1 = {
    uname: 'zs',
    pwd: '123456',
    login: function () {
      let fn = function () {
        console.log('用户' + this.uname + '的密码为' + this.pwd);
      }.bind(this) //仅改变了函数内this的指向,返回给fn
      //bind(this)中的this->user1
      setInterval(fn, 1000);
    }
  }
  user1.login() // 用户zs的密码为123456
衍伸

借用构造函数继承

 function Person(name, age, gender) {
    this.name = name
    this.age = age
    this.gender = gender
  }

  function Chinese(name, age, gender, skin) {
    Person.call(this, name, age, gender) // this指向Chinese的实例
    this.skin = skin || 'yellow'
  }
  let zs = new Chinese('张三', 20, 'male')
  console.log(zs); //Chinese {name: "张三", age: 20, gender: "male", skin: "yellow"}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值