zoukankan      html  css  js  c++  java
  • js中的call()和apply()和bind()方法

    call()、apply()、bind()的用法主要是纠正作用域中的this


    1.call()

    语法:obj1.call(obj2[,param1,param2,...])
    定义:用obj2对象来代替obj1,调用obj1的方法。即将obj1应用到obj2上。
    说明:call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 obj2 指定的新对象。 如果没有提供 obj2参数,那么 Global 对象被用作 obj2。

    原理

    Function.prototype.imitateCall = function (context) {
        // 赋值作用域参数,如果没有则默认为 window,即访问全局作用域对象
        context = context || window    
        // 绑定调用函数(.call之前的方法即this,前面提到过调用call方法会调用一遍自身,所以这里要存下来)
        context.invokFn = this    
        // 截取作用域对象参数后面的参数
        let args = [...arguments].slice(1)
        // 执行调用函数,记录拿取返回值
        let result = context.invokFn(...args)
        // 销毁调用函数,以免作用域污染
        Reflect.deleteProperty(context, 'invokFn')
        return result
    }

    2.apply()

    语法:obj1.call(obj2[,arrArg])
    定义:用obj2对象来代替obj1,调用obj1的方法。即将obj1应用到obj2上。

    说明:call ()和apply()作用一样,但是call()可以接收任何类型的参数,而apply()只能接收数组参数。

    作用:这两个函数都是在特定的作用域中调用函数,能改变函数的作用域,实际上是改变函数体内 this 的值 。

    原理

    Function.prototype.imitateApply = function (context) {
        // 赋值作用域参数,如果没有则默认为 window,即访问全局作用域对象
        context = context || window
        // 绑定调用函数(.call之前的方法即this,前面提到过调用call方法会调用一遍自身,所以这里要存下来)
        context.invokFn = this
        // 执行调用函数,需要对是否有参数做判断,记录拿取返回值
        let result
        if (arguments[1]) {
            result = context.invokFn(...arguments[1])
        } else {
            result = context.invokFn()
        }
        // 销毁调用函数,以免作用域污染
        Reflect.deleteProperty(context, 'invokFn')
        return result
    }

    3.基本用法

     function add(a,b){
            return a+b;
        }
        function sub(c,d){
            return c-d;
        }
        function result(){
            this.addValue = null;
            this.subValue = null;
            this.showResult=function(){
                alert(this.addValue);
                alert(this.subValue);
            }
        }   
        function myCallTest(){//此处this指向了add,如果不使用call则this指向window对象
                return add.call(this,7,2);
        }
        var r = new result();
        console.log(myCallTest());//9
        r.addValue = add.call(sub,4,2); //6,将add方法应用到sub上,即sub的指针指向add方法
        r.subValue = sub.call(add,4,2); //2,用add对象替换sub对象,并调用sub对象的方法
        r.showResult(); //在js中函数也是一个Function对象,函数名即是对象引用

    4.继承特性

    function add(a,b){
        return a+b;
    }
    function sub(c,d){
        return c-d;
    }
    function result(){
        this.addValue = null;
        this.subValue = null;
        this.showResult=function(){
            alert(this.addValue);
            alert(this.subValue);
        }
    }
    var r = new result();
    r.addValue = add.call(r,4,2);    //6,r继承add函数的所有特性
    r.subValue = sub.call(r,4,2);    //2,r集成sub函数的所有特性
    r.showResult();    

    5.bind()

    bind()函数也可以改变this指向,但是该函数返回了一个新的函数(绑定函数),当调用绑定函数时,会以bind的第一个参数作为当前作用域的上下文(this),之后的参数则作为原函数的属性。

    var write = document.write;
    write.bind(document)("hello!");

    这里write的this指向global或window,如果直接用write("hello!"),则非法调用(Illegal invocation),因为write的内部指向被修改为了window。所以需要bind重新调整索引,当然用call也可以。

    var write = document.write;
    write.call(document,"hello!");

    对比可以发现: call()、apply()都是立即执行的,bind()则是返回了一个函数,需再次调用才会执行。

    原理:

    Function.prototype.imitateBind = function (context) {
        // 获取绑定时的传参
        let args = [...arguments].slice(1),
            // 定义中转构造函数,用于通过原型连接绑定后的函数和调用bind的函数
            F = function () {},
            // 记录调用函数,生成闭包,用于返回函数被调用时执行
            self = this,
            // 定义返回(绑定)函数
            bound = function () {
                // 合并参数,绑定时和调用时分别传入的
                let finalArgs = [...args, ...arguments]
                
                // 改变作用域,注:aplly/call是立即执行函数,即绑定会直接调用
                // 这里之所以要使用instanceof做判断,是要区分是不是new xxx()调用的bind方法
                return self.call((this instanceof F ? this : context), ...finalArgs)
            }
        
        // 将调用函数的原型赋值到中转函数的原型上
        F.prototype = self.prototype
        // 通过原型的方式继承调用函数的原型
        bound.prototype = new F()
        
        return bound
    }

    转 : https://blog.csdn.net/mafan121/article/details/52922149

    https://www.cnblogs.com/Shd-Study/p/6560808.html

  • 相关阅读:
    统计nginx日志里访问次数最多的前十个IP
    while 格式化输出 运算符 字符编码
    Python 软件安装
    Python 基础
    Typora 基础的使用方法
    Django ORM (四) annotate,F,Q 查询
    Django 惰性机制
    Django ORM (三) 查询,删除,更新操作
    Django ORM (二) 增加操作
    Django ORM (一) 创建数据库和模型常用的字段类型参数及Field 重要参数介绍
  • 原文地址:https://www.cnblogs.com/fps2tao/p/15266772.html
Copyright © 2011-2022 走看看