this、apply、call 基础

1. this基础

除去不常用的with和eval,this的指向大致可以分为4种

  1. 作为对象的方法调用
  2. 作为普通函数调用
  3. 构造器调用
  4. Function.prototype.call 或者 Function.prototype.apply调用
1.1 作为对象的方法调用 - this 指向该对象
var obj = {
    a: 1,
    getA: function() {
        console.log(this === obj)
    }
}

obj.getA()  //  true
1.2 作为普通函数调用 - this 总是指向全局对象
window.name = 'globalName'
var getName = function() {
     return this.name
}
console.log(getName())  // globalName
window.name = 'globalName'

var myObject = {
    name: 'test',
    getName: function() {
        return this.name
    }
}

var getName = myObject.getName
console.log(getName())  // globalName
1.3 构造器调用

通常情况下: this 指向返回的这个对象
如果构造器显示的返回了一个object类型的对象,那么此次结果最终会返回这个对象,而不是this

var MyClass = function() {
    this.name = 'sven'
}

var obj1 = new MyClass()

console.log(obj1.name) // 'sven'
var MyClass = function() {
    this.name = 'sven'
    return {  //显示的返回了一个object类型的对象
        name1: 'sven111'
    }
}

var obj1 = new MyClass()

console.log(obj1.name)  // sven111
1.4 Function.prototype.call 或 Function.prototype.apply 调用 - 动态地改变传入函数的this
var obj2 = {
    name: 'sven',
    getName: function() {
        return this.name
    }
}

var obj3 = {
    name: 'anne'
}

console.log(obj2.getName()) // sven

console.log(obj2.getName.call(obj3))  // anne

2. call和apply

  1. apply 使用率更高,因为不用考虑数量
  • call(null, a, b, c)
  • apply(null, [a, b, c])
  • 在 call 或者 apply的时候,如果第一个参数是null,函数体的this会指向默认的宿主对象,在浏览器中则是window
  • 有时候使用call或者apply的目的不在于指定this指向,而是另有用途,比如借用其他对象的方法,那么可以传入null来代替某个具体的对象
console.log('Math.max.apply(null, [1, 2, 3, 4, 5])', Math.max.apply(null, [1, 2, 3, 4, 5])) // 5
console.log('[].shift.apply()', [].shift.call([1, 2, 3, 4, 5])) // 1
  1. call 和 apply 的用途
  • 改变this指向
  • Function.prototype.bind
  • 借用其他对象的方法
2.1 改变this的指向
var test1 = {
    name: 'sven'
}

var test2 = {
    name: 'anne'
}

window.name = 'window'

var getName1 = function() {
    console.log(this.name)
}

getName1() // window
getName1.call(test1) // sven
getName1.call(test2) // anne
2.2 Function.prototype.bind
Function.prototype.bind = function() {
    var self = this, // 保存原函数
        context = [].shift.call(arguments), // 需要绑定的this上下文
        args = [].slice.call(arguments) //  剩余参数转成数组
    return function() {
        return self.apply(context, [].concat.call(args, [].slice.call(arguments)))
            // 执行新的函数的时候,会把之前传入的context当做形函数体内的this
            // 并且组合两次分别传入的参数,作为形函数的参数
    }
}

var applyObj = {
    name: 'sven'
}

var func = function(a, b, c, d) {
    console.log('this.name', this.name)
    console.log('qqqqqqq', [a, b, c, d])
}.bind(applyObj, 1, 2)

func(3, 4)  // this.name sven  qqqqqqq [1, 2, 3, 4]
2.3 借用其他对象的方法
  • 借用构造函数:通过这种技术,可以实现一些类似继承的效果
  • 借用一些object的方法
var ObjA = function(name) {
    this.name = name
}

var ObjB = function() {
    ObjA.apply(this, arguments)
}

ObjB.prototype.getName = function() {
    return this.name
}

var b = new ObjB('test')
console.log('b', b.getName()) // test

// Array.prototype.push

var pushTest = function() {
    Array.prototype.push.call(arguments, 1)
    console.log('arguments', arguments)
}

pushTest(3, 4) // [3, 4, 2, 1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值