apply,call学习

一、this

例子1

var name = "windowName"
function getName() {
  var name = "jack"
  console.log(this.name)   // windowName
  console.log("inner", this)   // window
}

getName()
console.log("outer", this)  // window

this.namewindowName,因为调用的对象是window,getName() 相当于 window.getName()。如果使用严格模式的话,全局对象就是 <font color="red">undefined</font>

例子2

let name = "windowName"
let user = {
  name: 'jack',
  getName: function () {
    console.log(this.name)   // this 指向jack
  }
}
user.getName()

getName这个函数对象user调用的,应证了那句话“this 永远指向最后调用它的那个对象”

例子3

var name = "windowName"
var user = {
  name: null,
  getName: function () {
    console.log(this.name)   // windowName
  }
}
var fn = user.getName
fn()

因为把函数赋值给了fn,getName并没有调用,最后还是相当于window调用了这对方法,所以结果是 windowName<font color="red">不要在严格模式下</font>

this 的指向并不是在创建的时候就可以确定的,在 es5 中,永远是this 永远指向最后调用它的那个对象。

二、改变this的指向

  • 备份指针
  • 箭头函数
  • apply、call、bind

例子4

name = "windowName"
var user = {
  name: null,
  getName: function () {
    console.log(this.name)
  },
  test: function () {
    setTimeout(function () {
      this.getName()  // 报错 TypeError: this.getName is not a functionvar
    }, 100)
  }
}
user.test()

在不使用箭头函数的情况下,是会报错的,因为最后调用 setTimeout 的对象是 window,但是在 window 中并没有 func1 函数。

(1)箭头函数

箭头函数的 this 始终指向函数定义时的 this,而非执行时。

var name = "windowName"
var user = {
  name: "jack",
  getName: function () {
    console.log(this.name)   // this 指向jack
  },
  test: function () {
    setTimeout(() => {
      this.getName()
    }, 100)
  }
}
user.test()

箭头函数修正了this的指向

(2)备份指针

var name = "windowName"
var user = {
  name: "jack",
  getName: function () {
    console.log(this.name)   // tack
  },
  test: function () {
    var self = this  // 备份指针
    setTimeout(function () {
      self.getName()
    }, 100)
  }
}
user.test()

(3)apply、call、bind

使用 apply、call、bind 函数也是可以改变 this 的指向的

使用apply
var user = {
  name: "jack",
  getName: function () {
    console.log(this.name)   // jack
  },
  test: function () {
    setTimeout(function () {
      this.getName()
    }.apply(user), 100)
  }
}
user.test()

使用call

var user = {
  name: "jack",
  getName: function () {
    console.log(this.name)   // jack
  },
  test: function () {
    setTimeout(function () {
      this.getName()
    }.call(user), 100)
  }
}
user.test()

使用bind

var user = {
  name: "jack",
  getName: function () {
    console.log(this.name)   // jack
  },
  test: function () {
    setTimeout(function () {
      this.getName()
    }.bind(user)(), 100)
  }
}
user.test()

(4)apply、call、bind 区别

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或类似数组的对象)提供的参数

语法

func.apply(thisArg, [argsArray])

  • thisArg
    可选的。在 func 函数运行时使用的 this 值。请注意,this可能不是该方法看到的实际值:如果这个函数处于非严格模式下,则指定为 nullundefined 时会自动替换为指向全局对象,原始值会被包装。
  • argsArray 可选的。一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 func 函数。如果该参数的值为 nullundefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。 浏览器兼容性 请参阅本文底部内容。
  • 返回值 调用有指定this值和参数的函数的结果。
(5)call 和 apply的区别

applycall 基本类似,他们的区别只是传入的参数不同。

fun.call(thisArg[, arg1[, arg2[, ...]]])

call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。

例子 (apply)

var operation = {
  sum: function (a, b) {
    console.log(a + b)   // 3
  }
}

var a = operation.sum
a.apply(operation, [1, 2])

例子 (call)

var operation = {
  sum: function (a, b) {
    console.log(a + b)   // 3
  }
}

var a = operation.sum
a.call(operation, 1, 2)
(6)bind 和 apply、call 区别

还是刚刚的例子

var operation = {
  sum: function (a, b) {
    console.log(a + b)   // 3
  }
}

var a = operation.sum
a.bind(operation, 1, 2)()
(7)创建对象时候使用call
function Person(name, age) {
  this.name = name
  this.age = age
}
var person = new Person('jack', 18)
person.name // jack

简单的来看一下 new 的过程吧:

var person = new Person('jack', 18)

new Person {
  var obj = {}
  obj.__proto__ = myFunction.prototype;
  var result = myFunction.call(obj,"jack","18");
  return typeof result === 'obj'? result : obj;
}
  • 创建一个空对象
  • 将新创建的空对象的隐式原型指向其构造函数的显示原型
  • 使用 call 改变 this 的指向
  • 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值