学习前端的菜鸡对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 ...
随机推荐
- Linux下类似windows下_beginthread和_endthread 的多线程开发
在 windows下头文件中包含 #include<process.h> 就可以使用_beginthread进行线程创建.个人感觉挺方便的. 在linux下类似于_beginthread ...
- SRC是在本位置显示:source的缩写,源的意思 HREF是点击后连接的目标:HyperlinkReference,超链接引用
SRC是在本位置显示:source的缩写,源的意思HREF是点击后连接的目标:HyperlinkReference,超链接引用
- jquery 阻止冒泡事件和阻止默认事件
jQuery 冒泡和默认事件: <!DOCTYPE html> <html lang="en"> <head> <meta charset ...
- Nginx_status显示结果详解
打开:http://aabb.com/nginx_status会有如下显示Active connections: 2872server accepts handled requests294 ...
- 静态网页开发技术-HTML
今天我重新复习了一下静态网页开发技术,概括如下. 一 .HTML文档结构与基本语法 :放置了标签的文本文档,可供浏览器解释执行的网页文件 1.注释标记 2.标记 3.属性 二.基本标记与使用 1.网页 ...
- docker 操作
docker daemon 设置代理 http_proxy=109.105.4.17:8118 & systemctl start docker centos: Edit /etc/sysco ...
- shell脚本面试题
Q:1 Shell脚本是什么.它是必需的吗? 答:一个Shell脚本是一个文本文件,包含一个或多个命令.作为系统管理员,我们经常需要使用多个命令来完成一项任务,我们可以添加这些所有命令在一个文本文件( ...
- jquery 显示 隐藏
参考 http://www.w3school.com.cn/jquery/jquery_hide_show.asp $("#a").hide(); $("#a" ...
- SpringMVC上传文件的MultipartFile源码
零.MultipartFile上传文件的具体实例如下: http://blog.csdn.net/swingpyzf/article/details/20230865 一.具体类和方法 上传文件主要方 ...
- The value for the useBean class attribute is invalid.
报错如下: The value for the useBean class attribute com.JavaBeanTest is invalid. 解决方法: 在JavaBean代码中加入无参数 ...