javascript学习笔记--理解apply()、call()、bind() 以及caller、callee属性
来源:互联网 发布:linux 启动挂载 编辑:程序博客网 时间:2024/05/29 04:12
本文目录如下:
- 前言
- apply()、all()函数、bind()函数
- caller属性与callee属性
- 总结
前言
在公司做一些全栈开发,实际上也不算,啥都会一点儿,其中就包括前端的javascript脚本语言。之前有过一些代码经验(代码算不上精致,用面向对象语言,写面向过程的代码逻辑),最近,突然想,无论什么语言,多沉淀一下总是好的,于是有了这个博客专栏,希望用笔头记下自己学习的点点滴滴,欢迎大家拍砖。
apply()函数与call()函数
无论是小白还是老司机,相比对这两个大名鼎鼎的函数不陌生。先来看看这两个函数的基本描述:
- 对于javascript脚本语言,所有的函数都包含这两个函数,不需要任何的继承
- 他们的用途都是一样的,都是为了扩充函数的功能,有的说法也叫作用域,比较难以理解
- 接收参数方面不同,apply()接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
call()方法第一个参数与apply()方法相同,但传递给函数的参数必须列举出来。
对于前面两点,实际上还是比较好理解的,想必对于第三点,尤其是对于我这种小白来说,还是比较蒙逼的,什么是函数运行作用域?下面举个例子,然后看起运行的行为,然后我们再来重新进行定义,让第三点读起来通俗易懂。
//声明一个Person对象function Person(name){ this._name=name this.showName=function(){//打印自己名字的方法showName() return this._name; }}//声明一个Chinese对象,无showName()function Chines(name){ this._name = name; }}//声明一个American对象,showName()function American(name){ this._name = name; }}//从声明来看,这三个函数没有依赖关系;//那么现在Chinese和American都想有一个这样的方法,有什么解决思路呢?/* 1.继承 已经超出本文的研究范围,不做深入研究 2.在这两个对象中加上showName()方法,那如果是100个对象呢,是不是要写100遍这个函数,这个简直就是灾难 3.利用apply()和call方法*///ok,讨论完方案之后我们来改造下代码,当然我们直接摒弃了方法2,因为方法2太low了,我们来说下方法3function Chinese(name){ Persion.apply(this); this._name=name}//声明一个American对象,showName()function American(name){ Persion.apply(this); this._name=name}//wait 这不就是第二种方法吗,实际上还是要在每个对象上加代码,不过我们的代码看起来优雅了不少,下面来跑下测试结果看看var chinese = new Chinese("chenglong");var american = new American("john");console.log(chinese.showName()); //输出chenglongconsole.log(american.showName()); //输出john//通过apply,两对象就有了Person对象的方法了//当然用call方法也是一样的,不过call方法需要指定具体的参数,看起来像这个样子function Chinese(name){ Person.call(this,name); this._name=name}//声明一个American对象,showName()function American(name){ Person.call(this,name); this._name=name}var chinese = new Chinese("chenglong");var american = new American("john");console.log(chinese.showName()); //输出chenglongconsole.log(american.showName()); //输出john//你也可以不用继承的方式 这就退化成了普通的调用了,这种方式不必改造任何的代码//声明一个Chinese对象,无showName()function Chinese(name){ this._name = name;}//声明一个American对象,showName()function American(name){ this._name = name;}var person = new Persion("person");var chinese = new Chinese("chenglong");var american = new American("john");console.log(person.showName.apply(chinese)); //输出chenglongconsole.log(person.showName.call(chinese,"chenglong")); //输出chenglongconsole.log(person.showName.apply(american)); //输出johnconsole.log(person.showName.call(american,"john")); //输出john//看起来这种情况下,apply更优雅,但是没指定参数,总是发慌,用call限定了参数;而且多了个person对象,真让人不爽,因此把apply和call运用到类中,一劳永逸
现在,我们来总结一下,基本描述的第三点,在继承中我们有一句这样的代码Persion.call(this,name)和 Persion.apply(this),当有了这个代码之后,我们的Chineses从此就有了showName的方法,apply中文是啥意思?应用的意思,我们似乎可以这么拆解:将Person的所有的方法(或者某个方法)应用在apply()/call()传进来的第一个参数上,我们的函数对象(有一个对象A,有一些基础的方法,比如打印名字什么的,而有个对象B,不想重载这些方法,那这个时候就用apply()/call()来把A的方法扩展下吧,为我所用)这就达到了,将Chinese对象的方法进行扩展的目的,不得不佩服javascript语言发明者的绝妙思维。
bind()函数
实际上理解了call函数和apply函数之后,再来理解bind函数就没那么难了,bind函数从某种意义上来说,用法和上述两个函数一模一样。最大的区别是,bind函数具有懒加载,可以用着回调,该函数实际上返回的是一个更换了this指针的函数引用,你可以不立即执行它,将它保存在变量中,而apply和call就不行,你调用了就立即执行。举个例子:
var obj = { x: 100,};var foo = { getX: function() { return this.x; }}console.log(foo.getX.bind(obj)()); //100console.log(foo.getX.call(obj)); //100console.log(foo.getX.apply(obj)); //100//虽然结果都是一样的,但是你可以发现bind函数在后面多了一对小括号,这就是区别
caller和callee属性
caller:调用者的意思,返回的是谁是这个函数的调用者的函数引用。举个例子:
function callerDemo(){ if(arguments.caller){//调用者不是null,则返回调用者的函数引用 console.log(callerDemo.caller.toString()); }else { console.log("This function's caller is windows"); }}function handleCaller(){ callerDemo();}handleCaller();//输出的是handleCaller函数的引用callerDemo();//This function's caller is windows
callee:callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用。这个特性在递归函数中非常的有用。
function calleeDemo() { alert(arguments.callee);}callerDemo();//打印函数对象本身的引用
总结
最后,再总结一下:
- apply 、 call 、bind 三者都是用来改变函数的this对象的指向的,第一个参数都是传入的对象的this指针;
- bind函数返回的是函数,具备回调性质,apply、call立即调用
- caller 返回的是调用该函数的函数的引用;
- calee是argument的一个属性方法,返回的是这个函数的本身的引用
- apply、call、bind的通用理解方式是:xxx对象的xx方法运用到xxx对象上(obj.method.apply,call,bind),使得目标对象的方法得到了扩展
- javascript学习笔记--理解apply()、call()、bind() 以及caller、callee属性
- javascript 中arguments、call、apply、bind、callee、caller属性的简单理解
- Javascript - 全面理解 caller,callee,call,apply
- Javascript - 全面理解 caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 理解JavaScript的caller,callee,call,apply
- 谈谈javascript的Function中那些隐藏的属性/方法:caller/callee/apply/call/bind
- JavaScript apply、call、caller、callee、bind使用方法与区别分析
- js中的apply/call/caller/callee/bind
- 全面理解javascript的caller,callee,call,apply概念[摘]
- 全面理解javascript的caller,callee,call,apply概念
- 全面理解javascript的caller,callee,call,apply概念
- Java 多线程结束 的第二种方法 interrupt方法
- java8 流的使用学习笔记
- Sass语法(二)之函数
- libev库的用法
- Servlet中service()方法
- javascript学习笔记--理解apply()、call()、bind() 以及caller、callee属性
- sql之left join、right join、inner join的区别
- GDAL从源码到JAVA应用(Windows环境)
- 线程池原理
- 知识点--实际开发中软引用或弱引用的使用场景
- iOS view截屏
- Usage of CURL
- kolla(1)
- Day22--任务三总结