zoukankan      html  css  js  c++  java
  • apply、call和bind

    apply()和call()

    虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们还是可以控制this的指向的!
    要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数时在其中运行函数的作用域,第二个参数是Array的实例,也可以是arguments对象。

    另一个与apply()类似的方法是call(),唯一区别是:apply()把参数打包成Array再传入,call()把参数按顺序传入。比如调用Math.max(3, 5, 4),分别用apply()和call()实现如下:Math.max.apply(null, [3, 5, 4]); Math.max.call(null, 3, 5, 4); 对普通函数调用,我们通常把this绑定为null。

    function sum(num1, num2){
         return num1 + num2;
    }
    function callSum(num1, num2){
         return sum.call(this, num1, num2);
    }
    function callSum1(num1, num2){
         return sum.apply(this, arguments);
    }
    function callSum2(num1, num2){
          return sum.apply(this, [num1, num2]);
    }
    console.log(callSum(10,10));   //20
    console.log(callSum1(10,10));//20
    console.log(callSum2(10,10));//20

    apply和call常被用来扩展函数赖以运行的作用域。

    window.color = 'red';
    var o = {color:'blue'};
    function sayColor(){
        console.log(this.color);
    }
    sayColor();            //red
    sayColor.call(this);   //red
    sayColor.call(window); //red
    sayColor.call(o);      //blue

    在上面的例子中,定义了一个全局函数sayColor,在全局作用域中调用时,对this.color的求值会转换成对window.color的求值,sayColor.call(this)和sayColor.call(window)是两种显示地在全局作用域中调用函数的方式,结果都会显示"red",但是当运行sayColor.call(o)时,函数的执行环境就不一样了,此时函数内的this对象指向了o,于是结果显示"blue"。

    使用call()和apply()来扩充作用域的最大好处就是对象不需要与方法有任何耦合关系。

    function getAge(){
    var y = new Date().getFullYear();
        return y - this.birth;
    }
    var xiaoming = {
        name: '小明',
        birth: 1990,
        age: getAge
    };
    console.log(xiaoming.age());    //27
    console.log(getAge.apply(xiaoming,[]));   //27

    bind()

    bind()是ES5新增的方法,这个方法的主要作用就是将函数绑定到某个对象
      当在函数f()上调用bind()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。以函数调用的方式调用新的函数将会把原始的函数f()当做o的方法来调用,传入新函数的任何实参都将传入原始函数。

    function f(y){
        return this.x + y; //这个是待绑定的函数
    }
    var o = {x:1};//将要绑定的对象
    var g = f.bind(o); //在函数f()上调用bind()方法并传入一个对象o作为参数,得到一个新的函数g
    g(2);//3 

    上面的代码就是把原始的函数f()当做o的方法来调用 ,传入实参都将传入原始函数。

    var o={
        x:1
        f:function(y){
            return this.x + y;   //y=2
        }
    }

    bind()方法不仅是将函数绑定到一个对象,它还附带一些其他应用:除了第一个实参之外,传入bind()的实参也会绑定到this,这个附带的应用是一种常见的函数式编程技术,有时也被称为'柯里化'(currying)。

    var sum = function(x,y){
        return x+y;
    }
    var succ = sum.bind(null,1); //在函数sum上调用bind()方法并传入一个对象window,得到新的函数succ,并且还到了一个实参到该对象中
    succ(2); //3,x绑定到1,并传入2作为实参y
    
    function f(y,z){
        return this.x + y + z; //this指向当前调用的对象或Window
    }
    var g = f.bind({x:1},2);
    g(3); //6,this.x绑定到1,y绑定到2,z绑定到3

    常见用法

    找出数组的最大元素

     将类数组转换成真正的数组

    利用call和apply做继承

     利用bind实现函数柯里化

     

     实现call

    1,将函数设为对象的属性

    2,执行&删除这个函数

    3,指定this到函数并传入给定参数执行函数

    4,如果不传入参数,默认指向为window

    Function.prototype.myCall = function (context) {
        var context = context || window;
        context.fn = this;
    
        var args = [];
        for(var i = 1, len = arguments.length; i < len; i++) {
            args.push('arguments[' + i + ']');
        }
    
        var result = eval('context.fn(' + args +')');
    
        delete context.fn
        return result;
    }

     实现apply方法

    Function.prototype.myApply = function(context,arr){
                var context = Object(context) || window;
                context.fn = this;
                 var result;
                 if(!arr){
                     result = context.fn();
                 }else{
                     var args = [];
                     for(var i=0,len=arr.length;i<len;i++){
                         args.push("arr[" + i + "]");
                     }
                     result = eval("context.fn(" + args +")");
                 }
                 delete context.fn;
                 return result;
            }

     实现bind

    Function.prototype.myBind = function (context, ...args) {
        // 异常处理
        if (typeof this !== "function") {
          throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
        }
        // 保存this的值,它代表调用 bind 的函数
        var self = this;
        var fNOP = function () {};
    
        var fbound = function () {
            self.apply(this instanceof self ? 
                        this : 
                        context, args.concat(Array.prototype.slice.call(arguments)));
        }
    
        fNOP.prototype = this.prototype;
        fbound.prototype = new fNOP();
    
        return fbound;
    }
  • 相关阅读:
    xp系统优化
    项目开发文档格式13种 (转载)
    java 操作 ORACLE
    orclae temp table
    把EXCEL上传并BINDING到GRIDVIEW中
    从excel读数据写入数据库代码
    GMDatePicker控件的使用
    代码汇总
    dwr运行时出现Servlet.init() for servlet dwrinvoker threw exception的解决方法
    CVSNT安装
  • 原文地址:https://www.cnblogs.com/yuyujuan/p/9161641.html
Copyright © 2011-2022 走看看