本文章记录本人在学习 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 functionthrow 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各位共勉!

JS学习笔记 - 代码复用相关推荐

  1. nest.js学习笔记(一)

    nest.js学习笔记(一) 一.安装nest.js 前置条件 运行项目 目录介绍 二.nest.js cli 常用命令 三.RESTful 风格设计 1.接口url 2.RESTful 版本控制 四 ...

  2. backbone.js学习笔记

    backbone.js学习笔记 之前只接触过jQuery,看来Backbone是除了jQuery的第二大JS框架... backbone到底是个啥? 其实刚开始我也不知道=_=,我是这周二才听说居然还 ...

  3. node.js学习笔记

    # node.js学习笔记标签(空格分隔): node.js---## 一 内置模块学习 ### 1. http 模块 ``` //1 导入http模块 const http =require('ht ...

  4. WebGL three.js学习笔记 6种类型的纹理介绍及应用

    WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...

  5. html 流程控制,HTML5独家分享:原生JS学习笔记2——程序流程控制

    当当当当 .....楼主又来了!新一期的js学习笔记2--程序流程控制更新了! 想一键获取全部js学习笔记的可以给楼主留言哦! js中的程序控制语句 常见的程序有三种执行结构: 1.顺序结构 2.分支 ...

  6. node.js学习笔记5——核心模块1

    node.js学习笔记5--核心模块1 Node.js核心模块主要内容包括:(1)全局对象 (2)常用工具 (3)事件机制 (4)文件系统访问 (5)HTTP服务器与客户端 一: 全局对象 Node. ...

  7. Vue.js 学习笔记 五 常用的事件修饰符

    介绍几个常用的事件修饰符 直接上代码 <div id="divApp"><div class="divColor" v-on:click=&q ...

  8. Vue.js 学习笔记三,一些基础指令,v-bind,v-on

    在笔记二的基础上继续写 v-bind指令,为属性绑定数据 <!--v-bind指令可以绑定属性--><div v-html="msg2" v-bind:title ...

  9. Vue.js 学习笔记 一

    上手前的一些概念 为啥要用Vue.js Vue.js 是目前最流行的前端框架之一,专注于视图层,容易上手. 使用Vue.js,通过框架提供的指令可以减少很多DOM操作(数据的双向绑定),提高渲染效率, ...

最新文章

  1. 机器学习 LR getA()
  2. android平台自动化编译环境搭建一hudson安装
  3. C语言怎么筛选偶数出来,在excel里如何自动筛选出偶数值
  4. python2读取excel中文处理,【Python】【源码】利用Python读取Excel文件-续
  5. 云计算的概念_云计算概念掀起涨停潮 美利云奠定板块龙头地位
  6. Delphi XE7的Splash 功能
  7. matlab 约束函数,【优化求解】MATLAB约束优化之惩罚函数法
  8. spring mysql 中文_Spring+mysql+velocity 中文问题解决方法
  9. kali linux下sqlmap使用教程
  10. Vlfeat (Matlab安装)
  11. 为什么计算机能读懂 1 和 0
  12. Node.js基础入门第七天
  13. 【Python爬虫】爬取 LOL 全英雄全皮肤图片
  14. MATLAB如何去掉坐标轴上的数字或去掉坐标轴但保留刻度边框
  15. 为什么英语会有主格和宾格之分?比如:I、me
  16. 【干货】提取图片元数据之exiftool
  17. 新颖的自我介绍_精选简单新颖的自我介绍
  18. java中new一个对象时具体都发生了什么?
  19. codecombat计算机科学入门五(python)
  20. python 滤镜色卡

热门文章

  1. mysql查询时调用函数_【性能测试】性能测试时对Mysql数据库的慢查询监控
  2. ajax传递数组 php,jQuery.ajax向后台传递数组问题如何解决
  3. 用于面包板的双列直插需要多宽?
  4. Python - 移除List中重复项的五种常用方法
  5. 如何使得自己的Python程序每行长度小于80个字符?
  6. 第十五届全国大学生智能汽车竞赛山东赛区国赛获奖队伍详细信息
  7. 第十五届全国大学生智能车竞赛山东赛区比赛成绩和奖项
  8. 生命周期共有那几个阶段_一文搞懂ReactNative生命周期的进化
  9. 用计算机打印相片怎么调色,2018年底照片如何使用LOG模式进行调色
  10. 禅道测试套件怎么用_优质单元测试的十大标准,你有遵循吗?