• call、apply和bind的用法及区别


     一、call和apply

    1、call和apply都是function.prototype的方法,每一个方法的对象实例 new function() 都会有这两个属性;

    2、这两个属性都是针对方法的属性针对方法使用;

    3、call和apply使用方法相同;

    4、call和apply的参数不同;
    (1)test.call ( this, param1 , param2 , param3 ) ; // 可以传多个参数
    (2)test.apply ( this, paramArray ) ; // 只能传两个参数,第二个一般为数组

    二、bind

    call和apply会改变this指向,然后执行函数;
    bind会改变this指向后,返回一个绑定新this的函数;

    三、demo

    var name = "aven";
    var age = 18;
    
    var obj = {
          name: "ake",
          age: this.age,
          test: function(){
              console.log("name: ", this.name, "age: ", this.age );
      }
    };
    
    obj.test(); 
    // name: ake  age: undefined
    // 因为obj.test() 只会调用本身属性,本身没有age属性,但是有name属性
    
    obj.test.call()
    // name:  aven age:  18
    // call参数为null或undefined时默认指向window,
    // this含有属性 name : "aven", age: 18,所以输出结果变化
    var name = "testName";
    var age = 18;
    
    var obj = {
          name: "ake",
          age: this.age,
          test: function(gender, home){
              console.log("name: ",this.name,"age:",this.age,"gender:",gender,"home: ", home);
      }
    };
    
    var person = {
          name: "aven",
          age: 18
    }
    
    obj.test.call(person, "female", "China")  // name:  aven age: 18 gender: female home:  China
    obj.test.apply(person, ["female", "China"])  // name:  aven age: 18 gender: female home:  China
    obj.test.bind(person, "female", "China")()  // name:  aven age: 18 gender: female home:  China
    obj.test.bind(person, ["female", "China"])()  // name:  aven age: 18 gender: ["female", "China"] home:  undefined
    
    obj.test.bind(this, "female", "China")() // name:  testName age: 18 gender: female home:  China

    四、实现call方法

    Function.prototype.myCall = function () {
        var _this = arguments[0]
        var params = [...arguments].slice(1)
        var isStrict = (function () {return this === undefined})
        if (!isStrict) {
            // 如果是其他原始值,需要通过构造函数包装成对象
            var type = typeof _this;
            if (type === 'number') {
                _this = new Number(_this)
            } else if (type === 'string') {
                _this = new String(_this)
            } else if (type === 'boolean') {
                _this = new Boolean(_this)
            }
        } 
        var invokeFun = this;
        if (_this === null || _this === undefined) {
            return invokeFunc(...params)
        }
        var uniquePropName = Symbol(_this)
        _this[uniquePropName] = invokeFun
        return _this[uniquePropName](...params)
    }

    五、实现一个apply,跟call相似,把参数列表改为参数数组

    Function.prototype.myApply = function (_this, params) {
        var isStrict = (function() {return this === undefined}())
        if (!isStrict) {
            // 如果是其他原始值,需要通过构造函数包装成对象
            var type = typeof _this;
            if (type === 'number') {
                _this = new Number(_this)
            } else if (type === 'string') {
                _this = new String(_this)
            } else if (type === 'boolean') {
                _this = new Boolean(_this)
            }
        }
        var invokeFun = this
    
        var invokeParams = Array.isArray(params) ? params : []
        if (_this === null || _this === undefined) {
            return invokeFun(...invokeParams)
        }
        uniquePropName = Symbol(_this)
        _this[uniquePropName] = invokeFun
        return _this[uniquePropName](...invokeParams)
    }

    六、实现bind,区别在于

    Function.prototype.myBind = function() {
        var boundTargetFunc = this;
        if (typeof boundTargetFunc !== 'function') {
          throw new Error('绑定的目标必须是函数')
        }
        var boundThis = arguments[0];
        var boundParams = [].slice.call(arguments, 1);
        function fBound () {
          var restParams = [].slice.call(arguments);
          var allParams = boundParams.concat(restParams)
          return boundTargetFunc.apply(this instanceof fBound ? this : boundThis, allParams)
        }
        fBound.prototype = Object.create(boundTargetFunc.prototype || Function.prototype)
        return fBound
      }
  • 相关阅读:
    第三方库添加记录
    xcode之语法高亮效果消失解决办法
    将excel记录导入ms sql
    eWebEditor在IE8,IE7下所有按钮无效之解决办法
    关于对数据库中重复记录的操作
    javascript如何取得RadioButtonList的值
    水晶报表分页并自动插入空白行
    如何防止SQL注入
    VC++视频教程下载地址
    如何显示最近过生日的记录
  • 原文地址:https://www.cnblogs.com/liuabo/p/13608164.html
Copyright © 2020-2023  润新知