JS进修笔记 - 代码复用

本文章记录本人在进修 JavaScript 中看书明白到的一些东西,加深影象和而且整顿记录下来,轻易以后的温习。

js 中复用代码

说道代码复用,平常都邑涉及到对象继续。在js中有很多能够挑选的继续要领。这些要领关于进修和明白多种差别的形式有很大的优点,由于它们有助于供应对言语的控制水平。

然则在开辟的过程当中,并非一切的代码复用都邑运用到继续。个中一部缘由在于,事实上运用的js库可能以如许的或那样的体式格局处理了该题目。而另一方面的缘由就在于很少须要在js中竖立长而且庞杂的继续链。在静态强范例言语中,继续能够能是唯一复用代码的要领。在js中,常常有越发简约而且幽美的要领。包含:借用要领、绑定、复制属性以及从多个对象中混入属性等很多要领。

混入

混入是针对经由过程属性复制完成继续的思想做进一步的扩大,mix-in形式并非复制一个完全的对象,而是从多个对象中复制出恣意的成员并将这些成员组合成新的对象。

完成mix-in

function mix() {
    var arg, prop, child = {};
    for (arg = 0; arg < arguments.length; arg += 1) {
        for (prop in arguments[arg]) {
            if (arguments[arg].hasOwnProperty(prop)) {
                child[prop] = arguemnts[arg][prop];
            }
        }
    }
    return child;
}

mix-in完成异常简朴,只须要遍历每一个参数,而且复制出通报给该函数的每一个对象中的每一个属性。

借用要领

有的时刻,我们只须要对象中的一两个要领,然则又不想和对象构成父-子继续关联。只是想是用所须要的要领,而不愿望继续一切那些永久用不到的属性和要领。在这类情况下,能够经由过程运用借用要领形式来完成。

而这个要领是受益于call()apply()的。js中函数也是对象,而且它们本身也存在一些属性和要领,比方callapply()

运用call()apply()离别借用要领:

// call
notmyobj.doStuff.call(myobj, param1, p2, p3);

// apply
notmyobj.doStuff.apply(myobj, [param1, p2, p3]);

在晓得notmyobj对象上有doStuff要领的情况下,又想不继续notmyobj来运用doStuff要领。这个运用call()apply()就派上用场了。

另有一个场景是常常运用到借用要领的。那就是借用数组要领。由于数据具有很多很壮大的要领,而且有时刻须要操纵arguments的时刻会用上。然则arguments是一个伪数组,不具有原生数组壮大的要领。这个运用借用要领就派上用场了:

function f() {
    var args = [].slice.call(arguemnts, 1, 3);
    return args;
}

借用和绑定

考虑到借用要领不是经由过程挪用callapply()就是经由过程简朴的复制,在借用要领的内部,this所指向的对象是基于挪用表达式而肯定的,然则有的时刻“锁定”this的值,或许将其绑定到特定的对象而且预先肯定该对象。

举一栗子:

var one = {
    name: 'object',
    say: function (greet) {
        return greet + ", " + this.name;
    }
};

// 测试
one.say('hi'); // hi, object

接着另一对象two中没有say()要领,借用onesay()要领:

var two = {
    name: 'another object'
}
// 测试
one.say.call(two, 'hi'); // hi, another object

在上面的例子中,借用的say()要领的this是指向two的。然则在什么样的场景中,应当将函数指针赋值给一个全局变量,或许将该函数做为回调函数来通报?在客户端编程中有很多事宜和回调,因而确切发生了很多如许殽杂的事宜。

举一个栗子:

// 给变量赋值
// this 将指向全局变量
var say = one.say;
say('hello') // hello, undefined

// 作为回调通报
var yetanother = {
    name: 'yet another object',
    method: function (callback) {
        return callback('hola');
    }
};

// 测试
yetanother.method(one.say) // holla, undefined

在上面的两种情况下,say()要领的this值都是指向全局对象。而且全部代码都没法根据预期来运转。为了修复(绑定)对象与要领之间的关联。能够运用一个简朴的函数来完成:

function bind(o, m) {
    return function () {
        return m.apply(o, [].slice.call(arguments))
    }

上面的bind()要领接收两个参数。一个是对象o,另一个是要领m,并将二者绑定起来。然后返回一个函数。

运用bind()来处理题目:

var twosay = bind(two, one.say);
twosay('yo'); // yo another object

奢靡的具有绑定所须要辅佐的价值就是分外的闭包的开支。

ES5 bind()

ECMAScript5中给Function.protoype添加了一个bind()要领,使得bind()call()、apply()一样简朴易用。

然则在不支持ECMAScript5的运转环境下,我们能够本身完成一个bind()要领(来自 MDN):

if (!Function.prototype.bind) {
  Function.prototype.bind = function (oThis) {
    if (typeof this !== "function") {
      // closest thing possible to the ECMAScript 5 internal IsCallable function
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
    }

    var aArgs = Array.prototype.slice.call(arguments, 1), 
        fToBind = this, 
        fNOP = function () {},
        fBound = function () {
          return fToBind.apply(this instanceof fNOP && oThis
                                 ? this
                                 : oThis || window,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

    fNOP.prototype = this.prototype;
    fBound.prototype = new fNOP();

    return fBound;
  };
}

然后运用自带的bind()要领来重写一下上面的栗子:

var twosay = bind(two, one.say);
twosay('Bonjour'); // yo another object

末了,假如文章有什么毛病和疑问的处所,请指出。与sf列位共勉!

    原文作者:_我已经从中二毕业了
    原文地址: https://segmentfault.com/a/1190000002979897
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞