JavaScript—call, apply, bind 函数能干啥?(全)(20)
call(),apply(),bind() 函数大家可能都有所了解,但是在平时搬砖过程中很可能或者基本没用过,学过但都淡忘了。
但是在大量第三方的框架(库),甚至js自己都在 源码中大量使用 call,apply 函数。所以今天和大家仔细讨论下它们在 开发中的应用场景 。
1 . 它们是啥意思
1.1 作用
他们的作用都是改变函数内部的this。
这三个函数都是函数对象的方法,也就是说只有函数才可以直接调用这些方法。
1.2 三者区别
参数: 三个函数的第一个参数都是需要绑定的 this。
call: 可以有n个参数,从第二个参数开始的所有参数都是原函数的参数。
`apply`:只有两个参数,并且第二个参数必须为数组,数组中的所有元素一一对应原函数的参数。 `bind`: 只有一个参数,即要绑定的this。
call 语法: foo.call(this, arg1,arg2, ... ,argn ); apply 语法: foo.apply(this, [ arg1,arg2, ... ,argn ] ); bind 语法: foo.bind(this);
调用:
call,apply: 调用后立即执行原函数。
`bind`: 调用后返回已经绑定好this的函数。
小例子一枚:
function foo(a,b){ console.log(a+b); } foo.call(null,'海洋','饼干'); // 海洋饼干 这里this指向不重要就写null了 foo.apply(null, ['海洋','饼干'] ); // 海洋饼干 var fun = foo.bind(null); fun('海洋','饼干'); // 海洋饼干
2 .它们能干啥事
这是我们今天讨论的主题,这三个函数如何应用?什么情况下使用?能改变this指向又能咋滴?
2 .1 处理伪数组 (最常用)
先考虑一个问题,如果你使用var arr = document.getElementsByTagName('li')获取了5个li元素,你现在需要获取其中的第2,3,4三个元素,你会怎么做?
这样arr.slice(1,4);? 啊哦,TypeError -- arr.slice is not a function(slice不是函数),数组操作在日常搬砖中非常常见,我见过最傻的解决这个问题的方式是使用循环,将需要的元素一个个添加到一个新数组里0.0,下面我介绍的方法完全可以在实战中使用,可以给你的代码加分哦,非常方便简洁(中高级前端程序员中,算是基本操作了)。
先要介绍一个概念( 伪数组 ),这也是为什么我们刚刚slice切割数组时出错的原因: (对新手来说算是干货了,知道的可以跳过)
什么是伪数组?( 字面的意思已经呼之欲出了 )
有length属性
能按索引存储数据
能像遍历数组一样来遍历
不能使用数组的push()、slice()等方法
简单来说就是可以像数组一样操作的对象,但是没有数组的方法。
js中存在大量伪数组,如 :
1. function的arguments对象。 2. getElementsByName(),getElementsByTagName(),childNodes/children 等方法的返回值。 3. 还有比较常见的jquery,使用它获取的元素也是伪数组。
回到原来的问题,如何截取伪数组中的元素:伪数组没有这些方法,我们'借用'Array的slice不就行了
[].slice.call(arr,1,4); // 推荐写法
不想借用你可以直接给伪数组添加一个slice函数,如
arr.slice = [].slice; arr.slice(1,4);
当然,'借用' 更方便,直接添加会导致伪数组对象'污染'。
如果可以随意改变原对象,可以 直接将其转成真正的数组对象。
[].slice.call(arr);
2 .2 继承
继承方式多种多样,我们现在讨论的这种是其中很重要的一种实现方式,用call实现 js 构造函数继承 。
单继承
function person(name){ this.name = name } function man(name){ this.age = '男'; person.call(this,name); // 继承 man } var me = new man('海洋饼干'); console.log(me.name,me.age); // '海洋饼干' '男'
多继承
function person(name){ this.name = name } function man(name){ this.age = '男'; } function manProgrammer(name){ this.girlfriend = null; person.call(this,name); // 继承 person man.call(this,name); // 继承 man } var me = new manProgrammer('海洋饼干'); console.log(me.name,me.age,me.girlfriend); // '海洋饼干' '男' null
2 .3 this 硬绑定 --- bind
将一个对象强制且永久性绑定到函数的this上,使用call,apply或者其他的绑定方式都无法改变(除了new绑定,当然,可以手动撸一个new都无法改变的硬绑定)
直接看例子:
var fun ; var obj = { a : 1, foo : function(){ var _this = this; //平时有没有过这种写法? 为了防止this指向问题 //将this赋值给一个变量,间接维持了this的安全性 fun = function(){ console.log(_this.a); } } } obj.foo(); fun(); // 1 var obj1 = { a : 2} obj.foo.call(obj1); // 直接修改_this所绑定的值,boom了 fun(); // 2
但是这种方法感觉上是在逃避问题,直接不使用this了 ? 这真的不是什么好的解决问题的态度。下面使用我们的bind来优化一下:
var fun ; var obj = { a : 1, foo : function(){ // 不使用 _this, 避免无谓的变量声明 fun = function(){ console.log(this.a); }.bind(this); // 代码很简洁,很漂亮(b格) } } var obj1 = { a : 2} obj.foo(); fun(); // 1 fun.call(obj1); // 1 call ,apply等绑定 无法修改 // 这里和上面call的位置不同是因为this所处于不同的位置
这样替代 _this 很规(zhuang)范(b)呢
2 .4 取数组最大最小值
Math.max和min方法,接收多个参数,比较出极值,这里用到apply的一个默认功能:展开数组,传入一个数组参数就可以默认将这个数组转成一个个参数的形式赋给原函数
var num = [6,9,-3,-5]; console.log(Math.max.apply(Math,num)); // 9 等价 console.log(Math.max(6,9,-3,-5)); console.log(Math.min.apply(Math,num)); // -5 等价 console.log(Math.min(6,9,-3,-5));
2 .5 合并数组
合并数组常见有三种方式,1.循环 2.Array的concat() 3. 使用apply()合并
这里是使用最简便的apply
var a = [1,2,3]; var b = [4,5,6]; [].push.apply(a,b); // 借用数组的push方法 等价 a.push(4,5,6); console.log(a); // [1, 2, 3, 4, 5, 6]

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
JavaScript—ES6关于Promise的用法(19)
Node的产生,大大推动了Javascript这门语言在服务端的发展,使得前端人员可以以很低的门槛转向后端开发。 当然,这并不代表迸发成了全栈。全栈的技能很集中,绝不仅仅是前端会写一些HTML和一些交互,后台熟悉数据库的增删查改。 想必接触过Node的人都知道,Node是以异步(Async)回调著称的,其异步性提高了程序的执行效率,但同时也减少了程序的可读性。如果我们有几个异步操作,并且后一个操作需要前一个操作返回的数据才能执行,这样按照Node的一般执行规律,要实现有序的异步操作,通常是一层加一层嵌套下去。 为了解决这个问题,ES6提出了Promise的实现。 含义Promise 对象用于一个异步操作的最终完成(或失败)及其结果值的表示。简单点说,它就是用于处理异步操作的,异步处理成功了就执行成功的操作,异步处理失败了就捕获错误或者停止后续操作。 它的一般表示形式为: new Promise( /* executor */ function(resolve, reject) { if (/* success */) { // ...执行代码 resolve(); } else { /...
- 下一篇
Python全栈 Web(Flask框架、cookie, session)
cookie: 什么是cookie? 是一种数据存储技术 将一段文本保存在客户端的一种技术 并且可以长时间保存 cookie的使用场合: 记住密码 搜索关键词 在Flask使用cookie 使用 响应对象 来保存cookie到客户端 响应对象: resp = make_response("响应字符串") resp = redirect("地址") 响应对象.set_cookie(key, value, max_age) key: 保存cookie的名称 value: 保存cookie的值 max_age: 保存时间以 s 单位 session 什么是session session是保存在服务器为每个浏览器所开辟的一段空 session 在Flask中的实现 配置SECRET_KEY app.fonfig["SECRET_KEY"] = "YOURGUESS" 使用session
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
- SpringBoot2全家桶,快速入门学习开发网站教程
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- CentOS7设置SWAP分区,小内存服务器的救世主
- CentOS7安装Docker,走上虚拟化容器引擎之路
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS8安装Docker,最新的服务器搭配容器使用
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程