js中 call apply bind合集

在JavaScript中,call、apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向。

call、apply、bind方法的共同点和区别:

  • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
  • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文(函数的每次调用都会拥有一个特殊值——本次调用的上下文(context)——这就是this关键字的值。);
  • apply 、 call 、bind 三者都可以利用后续参数传参;

bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

1. call

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

定义:调用一个对象的一个方法,以另一个对象替换当前对象。

说明: call 方法可以用来代替另一个对象调用一个方法。
call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

thisObj的取值有以下4种情况:
(1) 不传,或者传null,undefined, 函数中的this指向window对象
(2) 传递另一个函数的函数名,函数中的this指向这个函数的引用
(3) 传递字符串、数值或布尔类型等基础类型,函数中的this指向其对应的包装对象,如 String、Number、Boolean
(4) 传递一个对象,函数中的this指向这个对象

function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name); //cheese
function a(){   
  console.log(this);   //输出函数a中的this对象
}       
function b(){}       
var c={name:"call"};    //定义对象c  

a.call();   //window
a.call(null);   //window
a.call(undefined);   //window
a.call(1);   //Number
a.call('');   //String
a.call(true);   //Boolean
a.call(b);   //function b(){}
a.call(c);   //Object
function Animal(){   
  this.name="animal";   
  this.showName=function(){   
    console.log(this.name);   
  }   
}   
function Dog(){   
  this.name="dog";   
}   
var animal=new Animal();   
var dog=new Dog();       

animal.showName.call(dog);//dog
//意思是把animal的方法放到dog上执行,也可以说,把animal 的showName()方法放到 dog上来执行,所以this.name 应该是 dog
function Animal(name){   
  this.name=name;   
  this.showName=function(){   
    console.log(this.name);   
  }   
}   
function Dog(name){   
  Animal.call(this,name);   
}   
var dog=new Dog("Crazy dog");   
dog.showName();//Crazy dog

//Animal.call(this) 的意思就是使用 Animal对象代替this对象,
//那么Dog就能直接调用Animal的所有属性和方法。类似继承。

2. apply

apply() 方法调用一个函数, 其具有一个指定的this值,以及作为一个数组(或[类似数组的对象])提供的参数。

语法:apply([thisObj[,argArray]])

说明:如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。

注意:call()方法的作用和 apply() 方法类似,只有一个区别,就是 call()方法接受的是若干个参数的列表,而apply()方法接受的是一个包含多个参数的数组

既然两者功能一样,那该用哪个呢?
在JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时用 call ;而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数。

/* min/max number in an array */
var numbers = [5, 6, 2, 3, 7];

/* using Math.min/Math.max apply */

/* This about equal to Math.max(numbers[0], ...) or Math.max(5, 6, ..) */
var max = Math.max.apply(null, numbers); 7
var min = Math.min.apply(null, numbers);1
var min = Math.min.call(null,5,6,2,3,7);1
1,函数之间的相互调用

function add(a,b){
    alert(a+b);
}

function sub(a,b){
    alert(a-b);
}

add.apply(sub,[5,6]); //11
add.call(sub,5,6); //11
从这里可以看出apply和call的参数方式是不一样的,
call的参数适合用于可明确值,且简短的参数,
apply的参数适合用于数组元素较多的场景。
2,构造函数之间的调用

function Person(){
     this.age = 50;
     this.showAge= function(){
           alert(this.age);
    }
}
function Son(){
    this.age  = 20;
}
var father  = new Person();
var xiaoming = new Son();
father.showAge();//50
xiaoming.showAge();//xiaoming.showAge is not a function

xiaoming 是没有showAge方法的,那如果想要知道xiaoming的年龄呢?

father.showAge.apply(xiaoming) //立即执行显示20
father.showAge.call(xiaoming)//立即执行显示20
xiaoming.showAge();报错,会说showAge() is not a function

此时说明将方法应用于另一个对象时,仅仅是对另一个对象执行此方法,结束之后,该对象不拥有此方法。

那么如果想要另一个对象也拥有这个方法呢?

还是刚刚的例子,我们在Son方法中添加代码:
function Son(){
    this.age  = 20;
    Person.call(this);
   //Person.apply(this)
}

var xiaoming = new Son();
xiaoming.showAge();//50  注意这里还是50哦 不是20  想想为啥?
------------------------------------------------------------------
function Son(){
    Person.call(this);
   //Person.apply(this)
   this.age  = 20;
}
var xiaoming = new Son();
xiaoming.showAge();//20  知道为啥了吧
3. Javascript 没有私有方法的概念,想用闭包实现
(function () {
    var Person = function () {
        this.doSomeThing = function () {
            _privateFunction.call(this);
        }
    }
    var _privateFunction = function () {
    }
    window.Person = Person;
}).call(window);
差不多就是这个意思,callback的时候,
当你希望你的callback中的上下文是当前上下文的时候,也可以用call或者apply,有什么好处呢?

这个时候你的callback 里面的this 就是指代当前上下文。
例如一个类Person,然后他的方法 say 有一个callback的参数,
如果这个callback是通过普通的括号来执行的话,
那在这个callback里面执行person的其它方法还需要用person.other 来实现,
但是切换上下文之后,就是this.other搞定~代码对比如下:
var Person = function(){
};
Person.prototype.say = function(callback){
    callback();
};
Person.prototype.other = function(){
};
var vincent = new Person();
vincent.say(function(){
    vincent.other();
});

用了call的:

var Person = function(){
};
Person.prototype.say = function(callback){
    callback.call(this);
};
Person.prototype.other = function(){
};
var vincent = new Person();
vincent.say(function(){
    this.other();
});

3. bind

bind()方法会创建一个新函数,称为绑定函数,当调用这个绑定函数时,绑定函数会以创建它时传入 bind()方法的第一个参数作为 this,传入 bind() 方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。

注意:bind方法的返回值是函数

var bar=function(){   
  console.log(this.a);   
}
var foo={ 
     a:3   
}   
bar();  //undefined
bar.bind(foo)(); //3
 /*或*/
var func=bar.bind(foo);   
func(); //3
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容