JavaScript之apply,call以及bind方法

来源:互联网 发布:电脑屏幕录制软件 免费 编辑:程序博客网 时间:2024/05/17 05:12

这几种方法在写web前端的时候用的并不是很多,但是在写web后台的时候真的是经常要用到,而且,理解这几种方法,可以写出很多高效而且优美的代码

在提到这几个函数之前,首先要知道,这几个函数都属于Function对象

一. 定义


1.call和apply方法

这里把apply和call归为一类,是因为他们都有一个共同点,都是要执行函数(从命名上就可以看出,都有运行的意思)

(1)call方法

  • 形式

call([thisObj[, arg1[, arg2[,  [, argN]]]]])

  • 参数

thisObj可选,将作为当前对象使用的对象

arg1, arg2, , argN可选,将被传递到该方法的参数列表

  • 定义
call 方法用于调用代表另一项目的方法,它允许您将函数的 this 对象从初始上下文变为由 thisObj 指定的新对象,如果没有提供 thisObj 参数,则 global 对象被用作 thisObj

第一个参数的使用:

var x = function() {console.log(this.value);}var obj = {value : 1}x.call(obj); //1x(); //underfined
可以看到,本来x是不存在value这个值,但是当把this对象替换成obj对象时,this.value就相当于是obj.value,所以就可以输出1了

后面参数的使用:

var x = function(a,b) {console.log(this.value + a + b);}var obj = {value : 1}x.call(obj,3,4); //8
后面参数就是真正要传递的参数,那么a=3,b=4


(2)apply方法

apply方法和call 方法用法基本一样,除了传递后面参数是通过数组来传递的

var x = function(a,b) {console.log(this.value + a + b);}var obj = {value : 1}x.apply(obj,[3,4]);


2. bind方法

之所以把bind方法提出来,是因为bind方法和apply或者call相比有本质的区别,从字面意思就可以看出,bind是绑定,而非执行

  • 形式
function.bind(thisArg[,arg1[,arg2[,argN]]])
  • 参数
function必选, 一个函数对象。
thisArg必选, this 关键字可在新函数中引用的对象
arg1[,arg2[,argN]]]可选, 要传递到新函数的参数的列表

  • 返回值

与 function 函数相同的新函数,thisArg 对象和初始参数除外

  • 定义

对于给定函数,创建具有与原始函数相同的主体的绑定函数,在绑定函数中,this 对象将解析为传入的对象,绑定函数具有指定的初始参数

var x = function(a,b) {console.log(this.value + a + b);}var obj = {value : 1}var y = x.bind(obj,3,4); //不输出任何信息,函数未执行y(); //8


二. 使用


1.继承

这种实现“继承”的方法十分巧妙,可以和原型链对比一下

function animal() {this.ear = 2;this.move = function() {console.log("I can move!");}}function monkey() {animal.apply(this); //换成call也行console.log(this.ear); //2this.move(); //I can move!}monkey();
可以看到,monkey继承了animal的属性和方法

之所以会这样,是因为这里把monkey的this对象当做animal的this对象传入,然后执行animal这个函数,这样,monkey的this对象在animal执行的过程中就添加了ear属性和move方法,由此实现了“继承”(因此,这里不能使用bind方法,因为bind方法只绑定,不执行)

这种方法一般使用在构造函数中,一般用来继承父类的属性


补充:

后面看了node.js,发现node.js的util模块提供了一个inherits方法,也是继承,而且经常和这个方法一起使用,我们可以看一下inherits的源代码:

exports.inherits = function(ctor, superCtor) {  ctor.super_ = superCtor;  ctor.prototype = Object.create(superCtor.prototype, {    constructor: {      value: ctor,      enumerable: false,      writable: true,      configurable: true    }  });};
发现inherits弥补了apply和call方法继承最关键的一点,就是没有继承原型链,因此只要一起使用,就是一个完整的继承了

var util = require('util');var myObj = function(){//code};myObj.prototype.get = function() {console.log("Hi!");}function Obj(params) {myObj.call(this);}util.inherits(Obj,myObj);(new Obj()).get(); //Hi!
这也是node.js推荐的继承方式,所以一定要掌握

2.传参

有的时候在写某个回调函数的时候,要传入某个参数,但这个参数却不怎么好传,比如这样:

function animal() {var arg = 3;session.on('closed', leave.bind(null, arg));}var leave = function(arg) {//操作};
在函数animal中,我想在session结束的时候回调leave函数,但需要传入一个arg参数,这时就可以使用bind方法
等价写法可以这样:

function animal() {var arg = 3;session.on('closed', function(arg){//操作});}

也可以这样:

function animal() {var arg = 3;session.on('closed', leave(arg));}var leave = function(arg) {return function(arg) {//操作}};

对比一下,使用bind写法既把leave函数分离了出来,又减少了代码量,应该会更灵活一些




1 0
原创粉丝点击