对象方法之this对象

一.this对象

之前的例子的sayName()直接引用了person.name,在方法和对象之间建立了紧耦合,这种紧耦合使得一个方法很难被不同对象使用。
Js所有函数作用域内都有一个this对象代表该函数的对象。在全局作用域内,this代表全局对象window,当一个函数作为对象的方法被调用时,默认this的值等于那个对象。改写:

name: "lucy", age="18"
var person = {
    name: "Nicholas",
    objName: this.name,
    sayName: function () {
        console.log(this.name  + "年龄" + this.age)  
    }
}
person.objName              // lucy
person.sayName             // Nicholas年龄undefined

所以应该在方法内引用this而不是直接引用对象。可以轻易改变变量名,或者将函数用在不同对象上,而不用大量改动代码。

function sayNameForAll() {
    console.log(this.name)
}
var person1={
    name: "Nicholas",
    sayName: sayNameForAll
}
var person2={
    name: "Greg" ,
    sayName: sayNameForAll
}
var name = "Micheal"
person1.sayName()                           // Nicholas 当前对象
person2.sayName()                           // Greg    当前对象
sayNameForAll()                             // Micheal  全局对象

this在函数被调用时才被设置,因此最后sayNameForAll函数执行时的this为全局对象。

二.改变this

有3种方法可以改变this,函数是对象,而对象可以有方法,所以函数也有方法。
1.call()
第一个用于操作this的方法是call(),它以指定的this和参数来执行函数,第一个参数为函数执行时的this的值后面的参数为需要被传入函数的参数。

function sayNameForAll (label) {
    console.log(label + ':' + this.name)
}
var person1 = {name: "Nicholas"}
var person2 = {name: "Greg"}
var name = "Micheal"
sayNameForAll.call(this,"global")                        // global:Micheal
sayNameForAll.call(person1, "person1")             // person1:Nicholas
sayNameForAll.call(person2,"person2")              // person2:Greg

2.apply()
第二个用于操作this的方法时apply(),其工作方式与call()完全一样,但它只接受两个参数:this的值和一个数组或者类似数组的对象,内含需要被传入函数的参数(可以把arguments对象作为apply的第二个参数)。

function sayNameForAll (label) {
    console.log(label + ":" + this.name)
}
var person1 =  {name:"Nicholas"}
var person2 = {name:"Greg"}
var name = "Micheal"
sayNameForAll.apply(this,["global"])                        // global:Micheal
sayNameForAll.apply(person1, ["person1"])             // person1:Nicholas
sayNameForAll.apply(person2,["person2"])              // person2:Greg

3.bind()
改变this的第三个函数方法为bind(),bind()的第一个参数是要传给新函数的this的值,其他参数代表需要被永久设置在新函数中的命名参数,可以在之后继续设置任何非永久参数。

function sayNameForAll (label) {
    console.log(label + ":" + this.name)
}
var person1 =  {name:"Nicholas"}
var person2 = {name:"Greg"}

var sayNameForPerson1 = sayNameForAll.bind(person1)
sayNameForPerson1("person1")                                         // person1:Nicholas
var sayNameForPerson2 = sayNameForAll.bind(person2,"person2")
sayNameForPerson2()                                                 // person2:Greg
person2.sayName = sayNameForPerson1;
person2.sayName("person2")                                          // person2:Nicholas

sayNameForPerson1()没有绑定永久参数,因此可以继续传入label参数输出,sayNameForPerson2()不仅绑定了person2作为this,而且绑定了第一个参数为person2,因此可以使用sayNameForPerson2()而不用传入额外参数,但是也不能更改了。person2.sayName最后由于this的值在sayNameForPerson1的函数表达式中已经绑定为person1了,所以虽然sayNameForPerson1现在是person2的方法,它依然输出person1.name的值。

4.call()、apply()、bind()区别

function sayNameForAll() {
    console.log(this.name + "年龄" + this.age)
}
var person1={
    name: "Nicholas",
    sayName: sayNameForAll
}
var person2={
    name: "Greg" ,
    obgAge: this.age,
    sayName: sayNameForAll
}
var obj = {
	name: "Micheal",
	age: "20"
}
person1.sayName.call(obj )                 // Micheal年龄20
person2.sayName.apply(obj)                // Micheal年龄20
sayNameForAll.bind(obj)()                 // Micheal年龄20

以上出了 bind 方法后面多了个 () 外 ,结果返回都一致!
由此得出结论,bind 返回的是一个新的函数,你必须调用它才会被执行。
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值