最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 手写call、apply、bind、new

    正文概述 掘金(MF16934)   2021-01-12   431

    call、apply、bind的使用方法及区别

    作用:这三个函数的作用都是用来改变this的指向

    call使用方法

    function fn1() {
        console.log(this)
    }
    const obj = { a: 1 }
    fn1.call(obj, 1, 2, 3, 4) // {a: 1}
    

    apply的用法

    function fn1() {
        console.log(this)
    }
    const obj = { a: 1 }
    fn1.apply(obj, [1, 2, 3, 4]) // {a: 1}
    

    bind的用法

    function fn1() {
        console.log(this)
    }
    const obj = { a: 1 }
    fn1.bind(obj, 1, 2, 3, 4) // 不会打印任何东西。
    

    乍一看,三者的用法几乎一致,需要注意的是bind函数,调用之后并没有执行fn1

    先看call和apply, 它们仅有的区别是传参的不同,call接收的是参数逐一传入,apply接收的是一个参数组成的数组

    接下来,来实现自己的call和apply函数,通过用法发现需要实现两点:

    • 改变执行函数的this指向为第一个参数
    • 执行原函数

    第二点好实现,来看第一点,通常情况下,当函数作为对象的方法调用时,this就指向这个对象,可以通过这个特点来实现自己的call函数

    // 因为需要所有函数都可以调用,所以需要写在Function的原型上
    Function.prototype.myCall(context) {
    	// 判断context是否存在,不存在设置为window
        context = context ? Object(context) : window
        // 处理参数
        const args = [...arguments].slice(1)
        // 要将this指向改为context,需要用context来调用
        context.fn = this // 这里的this是原函数
        const result = context.fn(...args) // 执行原函数,此时因为是context调用,因此函数中的this指向了context
        delete context.fn
        return result
    }
    

    实现自己的apply函数只需要修改传参方式即可

    // 因为需要所有函数都可以调用,所以需要写在Function的原型上
    Function.prototype.myCall(context) {
    	// 判断context是否存在,不存在设置为window
        context = context ? Object(context) : window
        // 要将this指向改为context,需要用context来调用
        context.fn = this // 这里的this是原函数
        
        let result
        // 处理参数
       if (arguments[1]) {
       	result = context.fn(...arguments[1])
       } else {
       	result = context.fn()
       }
        delete context.fn
        return result
    }
    

    接下来实现bind函数,bind与前两者较大不同是它创建了一个新的函数,并且它第一个参数被指定为这个新函数的this

    • 返回一个新函数
    • 第一个参数被指定为新函数的this
    • 其余参数被当作新函数的参数
    Function.prototype.myBind(context) {
    	const args = [...arguments].slice(1)
    	const that = this
    	return function() {
        	that.apply(context, args.concat(...arguments))
        }
    }
    

    接下来了解一下new运算符

    new的用法

    function Animal(type) {
    	this.type = type
        this.age = age
    }
    const animal1 = new Animal('猫', 2)
    const animal2 = new Animal('狗', 2)
    

    当执行new Animal()的时候,做了以下几件事情

    • 创建一个空对象
    • 改变this指向到这个空对象,并且让这个对象能访问到构造函数原型上的属性
    • 执行构造函数,此时的this指向了新创建的对象

    模拟生成new函数

    function _new() {
    	// 创建一个新对象
        let obj = {}
        // 获取传入的构造函数
        let constructor = [].shift.call(arguments)
        // 让这个对象能访问到构造函数原型上的属性
        obj.__proto__ = constructor.prototype
        // 改变this指向,并执行构造函数
        constructor.apply(obj, aruguments) // 这里的arguments已经经过截取处理
        // 返回创建的实例对象
        return obj
    }
    

    起源地下载网 » 手写call、apply、bind、new

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元