学习前端的菜鸡对JS的call,apply,bind的通俗易懂理解
call,apply,bind
在JavaScript中,call
、apply
和bind
是Function
对象自带的三个方法,都是为了改变函数体内部 this
的指向。
apply 、 call 、bind
三者第一个参数都是 this
要指向的对象,也就是想指定的上下文;
apply 、 call 、bind
三者都可以利用后续参数传参;
bind 是返回对应 函数,便于稍后调用;apply 、call
则是立即调用 。
——————————————————————————————————————————————————————————————————————————-
例子:
1.
function fruits() {} fruits.prototype = {
color: 'red',
say: function() {
console.log('My color is' + this.color);
}
} var apple = new fruits;
apple.say(); // 此时方法里面的this 指的是fruits
// 结果: My color is red
但是如果我们有一个对象 banana= {color : 'yellow'}
,我们不想重新定义 say 方法,那么我们可以通过 call 或 apply 用 apple 的 say 方法:
banana = {
color: 'yellow'
}
apple.say.call(banana); //此时的this的指向已经同过call()方法改变了,指向的是banana,this.color就是banana.color='yellow';
//结果是My color is yellow
apple.say.apply(banana);//同理,此时的this的指向已经同过apply()方法改变了,指向的是banana,this.color就是banana.color ='yellow';
//My color is yellow
// 如果传入的是 null: apple.say.apply(null); // null是window下的,此时,this 就指向了window ,但是window下并没有clolr这个属性,因此this.clolr就是window.color=undefined;
//My color is undefined
2.对于 apply、call 二者而言,作用完全一样,只是接受 参数 的方式不太一样。call 是把参数按顺序传递进去,而 apply 则是把参数放在数组 里。
var array1 = [12,'foo',{name:'Joe'},-2458];
var array2 = ['Doe' , 555 , 100];
Array.prototype.push.call(array1, array2);
// 这里用 call 第二个参数不会把 array2 当成一个数组,而是一个元素
//等价于array1.push(‘‘'Doe' , 555 , 100’’);
//array1.length=5; Array.prototype.push.apply(array1, array2); // 这里用 apply 第二个参数是一个数组 // 等价于: array1.push('Doe' , 555 , 100);
//array1.length=7;
3.类(伪)数组使用数组方法
var divElements = document.getElementsByTagName('div'); //虽然 divElements 有length属性,但是他是一个伪数组,不能使用数组里面的方法
Array.isArray(divElements);// false var domNodes = Array.prototype.slice.call(document.getElementsByTagName('div'));
// 将数组对象Array里的this指向伪数组document.getElementsByTagName('div'),
//slice() 方法可从已有的数组中返回选定的元素,不传参数是,返回整个数组
Array.isArray(domNodes);// true
4. 验证一个对象的类型可以用:
Object.prototype.toString.call(obj)
5.bind()
方法,MDN 的解释是:bind()
方法会创建一个 新函数,称为绑定函数,当调用这个绑定函数时,
绑定函数会以创建它时传入 bind()
方法的第一个参数 作为 this
,传入 bind()
方法的 第二个以及以后的参
数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数。
var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
bar(); // undefined
var func = bar.bind(foo); //此时this已经指向了foo,但是用bind()方法并不会立即执行,而是创建一个新函数,如果要直接调用的话 可以 bar.bind(foo)()
func(); //
6.在 Javascript 中,多次 bind()
是无效的。更深层次的原因, bind()
的实现,相当于使用函数在内部包了一个 call / apply
,第二次 bind()
相当于再包住第一次 bind()
,故第二次以后的 bind
是无法生效的。
var bar = function(){
console.log(this.x);
}
var foo = {
x:3
}
var sed = {
x:4
}
var func = bar.bind(foo).bind(sed);
func(); // var fiv = {
x:5
}
var func = bar.bind(foo).bind(sed).bind(fiv);
func(); //
7.apply、call、bind
三者相比较,之间又有什么异同呢?何时使用 apply、call
,何时使用 bind
呢。简单的一个例子:
var obj = {
x: 81,
}; var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //
console.log(foo.getX.call(obj)); //
console.log(foo.getX.apply(obj)); //
参考:
学习前端的菜鸡对JS的call,apply,bind的通俗易懂理解的更多相关文章
- 学习前端的菜鸡对JS 的classList理解
classList 在早期的时候要添加,删除类 需要用className去获取,然后通过正则表达式去判断这个类是否存在. 代码上去会有点麻烦,现在有了classList 就方便了很多. ——————— ...
- JS 的 call apply bind 方法
js的call apply bind 方法都很常见,目的都是为了改变某个方法的执行环境(context) call call([thisObj[,arg1[, arg2[, [,.argN]]]] ...
- js: this,call,apply,bind 总结
对js中的一些基本的很重要的概念做一些总结,对进一步学习js很重. 一.this JavaScript 中的 this 总是指向一个对象,而具体指向那个对象是在运行时基于函数的执行环境动态绑定的,而非 ...
- js call apply bind简单的理解
相同点:JS中call与apply方法可以改变某个函数执行的上下文环境,也就是可以改变函数内this的指向.区别:call与apply方法的参数中,第一个参数都是指定的上下文环境或者指定的对象,而ca ...
- 前端基础:call,apply,bind的的理解
背景 前两天在做小程序的需求的时候用到bind的时候才想起自己对这三的东西的了解比较浅薄,这个时候用的时候就有点怕.时候还是要好好学习下,理解下怎么玩. 正文 先说call 和 apply吧:ECMA ...
- js 中call,apply,bind的区别
call.apply.bind方法的共同点与区别: apply.call.bind 三者都是用来改变函数的this对象的指向: apply.call.bind 三者都可以利用后续参数传参: bind ...
- 原生JS实现call,apply,bind函数
1. 前言 使用原生JS实现call和apply函数,充分了解其内部原理.call和apply都是为了解决改变this的指向.作用都相同,只是传参的方式不同.除了第一个参数外,call可以接受一个参数 ...
- js笔记——call,apply,bind使用笔记
call和apply obj.call(thisObj, arg1, arg2, ...); obj.apply(thisObj, [arg1, arg2, ...]); 两者作用一致,都是把obj( ...
- JS之call/apply/bind
测试代码: var a = 1; var obj = { a = 2; } function test(a){ alert(a); alert(this.a); } 1.test(3); 结果:3,1 ...
随机推荐
- Safari-IoS调试
打开Safari浏览器,进入扩展功能,打开开发功能. 手机模拟器在设置中选择 javascript调试允许. 在模拟器中的页面,在Safari浏览器-开发模式-Serinator中选择打开的页面,即可 ...
- 扩展C#与元编程(二)
如果你对Windows Workflow Foundation(WF)一无所知,当看到扩展C#与元编程(一)中由MW编译器生成的FirstLook.mw.cs时,也许这么在想:我KAO,这是C#版的汇 ...
- too few PGs per OSD (20 < min 30)
ceph osd pool set replicapool pg_num 150 ceph osd pool set replicapool pgp_num 150
- Java8 Map的遍历方式
在这篇文章中,我将对Map的遍历方式做一个对比和总结,将分别从JAVA8之前和JAVA8做一个遍历方式的对比,亲测可行. public class LambdaMap { private Map< ...
- INI
.ini 文件是Initialization File的缩写,即初始化文件,是windows的系统配置文件所采用的存储格式,统管windows的各项配置,一般用户就用windows提供的各项图形化管理 ...
- 97. Interleaving String (String; DP)
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example,Given:s1 = ...
- Java数据类型与MySql数据类型对照表
这篇文章主要介绍了Java数据类型与MySql数据类型对照表,以表格形式分析了java与mysql对应数据类型,并简单讲述了数据类型的选择与使用方法,需要的朋友可以参考下 本文讲述了Java数据类型与 ...
- [leetcode]721. Accounts Merge账户合并
Given a list accounts, each element accounts[i] is a list of strings, where the first element accoun ...
- 零基础学习hadoop到上手工作线路指导(编程篇)
问题导读: 1.hadoop编程需要哪些基础? 2.hadoop编程需要注意哪些问题? 3.如何创建mapreduce程序及其包含几部分? 4.如何远程连接eclipse,可能会遇到什么问题? 5.如 ...
- RPM包制作方法
一.RPM介绍 RPM 前是Red Hat Package Manager 的缩写,本意是Red Hat 软件包管理,顾名思义是Red Hat 贡献出来的软件包管理:现在应为RPM Package M ...