• JavaScript中的call和apply应用


    ECMAScript3给Function的原型定义了两个方法,他们是Function.prototype.call 和 Function.prototype.apply. 在实际开发中,特别是在一些函数式风格的代码编写中,callapply方法尤为有用。

    call和apply区别

    其实他们的作用是一样的,只是传递的参数不一样而已。
    apply: 接受2个参数,第一个参数指定了函数体内this对象的指向,第二个参数为数组或者一个类数组。apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。

    举个栗子:

    const obj1 = {
    name: 'microzz',
    getName: function() {
    return this.name;
    }
    };
     
    const obj2 = {
    name: 'Zhaohui'
    }
     
    console.log(obj1.getName()); // "microzz"
    console.log(obj1.getName.call(obj2)); // "Zhaohui"
    console.log(obj1.getName.apply(obj2)); // "Zhaohui"

    call和apply的用途

    改变this指向

    call和apply可以改变this的指向,这点我们从上面这个例子中可以看出。我们还可以举一个实际当中可以遇到的情况:

    有的时候我们会觉得 document.getElementById这个方法太长了,我们会尝试用一个短函数来代替它,如同prototype.js等一些框架所做过的事情,下面用代码说明:

    const getId = function(id) {
    return document.getElementById(id);
    }
     
    getId('id');

    在Chrome、Firefox、IE10中执行会发现抛出异常,这是因为很多引擎的 document.getElementById 的方法内部需要用到this,这个this本来被期望指向document,但直接普通函数调用就指向了window。我们可以利用apply“修正” this

    document.getElementById = (function(func) {
    return function() {
    return func.apply(document, arguments);
    }
    })(document.getElement);
     
    const getId = document.getElementById;

    Function.prototype.bind

    在大部分高级浏览器已经实现了内置的Function.prototype.bind,用来指定函数内部的this指向,如果没有原生的Function.prototype.bind,我们也可以模拟一个,代码如下:

    Function.prototype.bind = function(context) {
    var self = this;
    return function() {
    return self.apply(context, arguments);
    }
    }
     
    var obj = {
    name: 'microzz'
    };
     
    var func = function() {
    console.log(this.name); // microzz
    }.bind(obj);
     
    func();

    这是一个简化版的,通常我们会实现得稍微复杂一点:

     
    Function.prototype.bind = function() {
    var self = this;
     
    // 需要绑定的this上下文
    var context = [].shift.call(arguments);
     
    // 剩余的参数转成数组
    var args = [].slice.call(arguments);
     
    return function() {
    return self.apply(context, [].concat.call(args, [].slice.call(arguments)));
    }
    }
     
    var obj = {
    name: 'microzz'
    };
     
    var func = function(a, b, c, d) {
    console.log(this.name); // microzz
    console.log([a, b, c, d]); // [1, 2, 3, 4]
    }.bind(obj, 1, 2);
     
    func(3, 4);

    借用其他对象的方法

    借用构造函数

    借用方法的第一种场景是“借用构造函数”,可以实现类似继承的效果:

    var A = function(name) {
    this.name = name;
    }
     
    var B = function() {
    A.apply(this, arguments);
    }
     
    B.prototype.getName = function() {
    return this.name;
    }
     
    var b = new B('microzz');
    console.log(b.getName()); // microzz

    类数组

    函数参数列表arguments是一个类数组对象,虽然它有下标,但是并不是真正的数组。为了能使用数组的一些方法,我们常常会借用Array.prototype对象上的方法。
    比如想往arguments中添加新元素,通常会借用Array.prototype.push
    想把arguments转成真正数组的时候,可以借用Array.prototype.slice或者也可以使用ES6的Array.from

    About

  • 相关阅读:
    unomi漏洞复现
    xxl-job漏洞复现
    cgi漏洞复现
    celery漏洞复现
    bash漏洞复现
    学习ASP.NET的一些学习资源
    用EF DataBase First做一个简单的MVC3报名页面
    怎样在Word中插入代码并保持代码原始样式不变
    安装notepad++之后怎样在鼠标右键上加上Edit with notepad++
    安装Visual Studio 2010之后怎样安装MSDN Library
  • 原文地址:https://www.cnblogs.com/libin-1/p/6810710.html
Copyright © 2020-2023  润新知