栋栋晓12:Javascript学习总结:函数声明和函数表达式的区别,apply和call的区别,
2015-03-23 16:02
746 查看
函数声明和函数表达式的区别,apply和call的区别,,
这一章是javascript函数里面的比较难的技术点,掌握我谈不上,我说下我的理解和别人的理解。
1.函数声明和函数表达式的区别?
创建函数的最常用的两个方法是函数表达式和函数声明
函数声明语句
函数定义表达式
这两种写法差不多,在应用中貌似也都是可行的,那他们有什么差别呢?
事实上,js的解析器对函数声明与函数表达式并不是一视同仁地对待的。对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析,而函数表达式,如同定义其它基本类型的变量一样,只在执行到某一句时也会对其进行解析,所以在实际中,它们还是会有差异的,具体表现在,当使用函数声明的形式来定义函数时,可将调用方式在函数声明之后,而后者,这样做的话会报错。
2.apply和call的区别?
函数调用
通过call和apply间接调用函数(改变this)
call 和 apply带有多个参数,call和apply把当前函数的this指向第一个参数给定的函数或对象中,并传递其余所有的参数作为当前函数的参数。
总结:call和apply方法的作用相同,就是参数不同,
call和apply的第一个参数都是一样的,但是后面参数不同,
apply第二个参数是个数组,
call从第二个参数开始后面有许多参数。
Call和apply的作用是什么:
Call和apply是改变函数的作用域(有些书里叫做改变函数的上下文)
下面看看大牛chshouyu的理解和讲解。
在Javascript中,每个函数都包含两个非继承而来的方法,call和apply。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内的this对象的值。
摘自《JavaScript高级程序设计》
apply方法接收两个参数,第一个参数是在其中运行函数的作用域,第二个是一个参数数组或者arguments对象。
call方法与apply方法作用相同,第一个参数也相同,区别在于,其余的参数需要逐个列出。
是使用call还是apply要看具体的情况。如果你知道所有参数或者参数的数量不多,可以使用call;如果参数的数量不确定,或者数量很大,或者你收到的是一个数组或者是个arguments对象,则需要使用apply。
下面是使用apply的一些典型例子
事实上,call和apply真正的用武之地在于,他们能够扩充函数赖以运行的作用域。
我们再来看下面的例子
前两个输出相同,因为在全局作用域,this即为window(浏览器环境)。
剩下的两个,我们分别改变了他们的执行环境,分别指向了o1和o2,于是结果就是显示对象各自的name值。
那么,使用call和apply有什么好处呢?我们发现,同样的一个函数,当指定不同的执行环境时,会产生不同的结果,这么做的一个最大的好处就是解耦。
使用call和apply,函数和对象没有强依赖关系,多个对象可以使用同一个函数,避免了资源的浪费,同时对于模块化编程也大有帮助。
如果你仍然对call和apply没有清晰的认识,可以试着这样理解。
我们把方法比作是工具,比如一把刀;而变量是具体的实物,比如一个苹果。我们可以使用这把刀切很多不同的苹果,在切苹果的过程中,实际上就是改变了刀的作用对象—不同的苹果。
在上面的例子
slice是一个方法,但是它是属于Array对象prototype属性所有的,在对arguments使用时,我们可以理解为借用。
比如张三会砍树,即张三有砍树这个方法(至于张三有没有树无所谓),而李四有树,但他却不会砍,这时李四便可以借用张三砍树的方法来砍自己的树,写成代码就是
还有一种情况是,李四自己也会砍树,但是有一天他病了,砍不动了,这时他也可以借用张三的砍树方法砍自己的树。在代码中就是
到了这里,相信你对call和apply已经有了一个比较形象的认识了。以后再遇到类似的问题时,不妨想象成现实中的关系,可能困扰许久的问题就豁然开朗了。
call和apply另外一个应用就是函数的柯里化和反柯里化技术,有兴趣的可以看下面两篇文章:
http://sombie.diandian.com/post/2013-06-28/40050585369
http://www.alloyteam.com/2013/08/javascript-zhong-you-qu-di-fan-ke-li-hua-ji-shu/
3.call和apply的适用场景 来源大牛丁文森
call和apply的作用很简单,就是改变上下文,适用场景太多了,虽然有时候只是为了“美观”,下面几个是我常用的。
1.
用来判断 Obj 的类型
arguments 虽然和Array 很像,但是他没有Array的push之类的方法,怎么办?
3.Javascript 没有私有方法的概念,想用闭包实现
差不多就是这个意思,callback的时候,当你希望你的callback中的上下文是当前上下文的时候,也可以用call或者apply,有什么好处呢?
这个时候你的callback 里面的this 就是指代当前上下文。例如一个类Person,然后他的方法 say 有一个callback的参数,如果这个callback是通过普通的括号来执行的话,那在这个callback里面执行person的其它方法还需要用person.other 来实现,但是切换上下文之后,就是this.other搞定~代码对比如下:
用了call的:
这一章是javascript函数里面的比较难的技术点,掌握我谈不上,我说下我的理解和别人的理解。
1.函数声明和函数表达式的区别?
创建函数的最常用的两个方法是函数表达式和函数声明
函数声明语句
function plus(x ,y) { }
函数定义表达式
var plus = function (x, y) { }
这两种写法差不多,在应用中貌似也都是可行的,那他们有什么差别呢?
事实上,js的解析器对函数声明与函数表达式并不是一视同仁地对待的。对于函数声明,js解析器会优先读取,确保在所有代码执行之前声明已经被解析,而函数表达式,如同定义其它基本类型的变量一样,只在执行到某一句时也会对其进行解析,所以在实际中,它们还是会有差异的,具体表现在,当使用函数声明的形式来定义函数时,可将调用方式在函数声明之后,而后者,这样做的话会报错。
2.apply和call的区别?
函数调用
作为函数调用 function a(){}; a();
作为方法调用 a={}; a.x = function(){}; a.x();
通过call和apply间接调用函数(改变this)
call 和 apply带有多个参数,call和apply把当前函数的this指向第一个参数给定的函数或对象中,并传递其余所有的参数作为当前函数的参数。
var O = function () { this.foo = 'hello'; this.hello = function () { return 'world'; } }; var fn = function () { console.log('call', this); }; var o = new O(); fn.call(o);//此时fn的this指向o
call和apply的不同之处,在于call传递的参数是作为arguments依次传入的,例如 fn.call(o, 1, 2, 3); 而apply传递的参数是以一个数组的方式传入的,例如 fn.apply(o, [1, 2, 3]);
总结:call和apply方法的作用相同,就是参数不同,
call和apply的第一个参数都是一样的,但是后面参数不同,
apply第二个参数是个数组,
call从第二个参数开始后面有许多参数。
Call和apply的作用是什么:
Call和apply是改变函数的作用域(有些书里叫做改变函数的上下文)
下面看看大牛chshouyu的理解和讲解。
在Javascript中,每个函数都包含两个非继承而来的方法,call和apply。这两个方法的用途都是在特定的作用域中调用函数,实际上等于设置函数体内的this对象的值。
摘自《JavaScript高级程序设计》
apply方法接收两个参数,第一个参数是在其中运行函数的作用域,第二个是一个参数数组或者arguments对象。
call方法与apply方法作用相同,第一个参数也相同,区别在于,其余的参数需要逐个列出。
apply(thisArg, argArray); call(thisArg[,arg1,arg2…]);
是使用call还是apply要看具体的情况。如果你知道所有参数或者参数的数量不多,可以使用call;如果参数的数量不确定,或者数量很大,或者你收到的是一个数组或者是个arguments对象,则需要使用apply。
下面是使用apply的一些典型例子
// 获得数组中最大的元素 var arr = [1, 8, 10, 3, 24, 89, 26]; var m = Math.max.apply(Math, arr); // m => 89 // 将类数组的对象转为数组 var arr = Array.prototype.slice.call(arguments);
事实上,call和apply真正的用武之地在于,他们能够扩充函数赖以运行的作用域。
我们再来看下面的例子
var name = 'out'; var o1 = { name: 'hello' }; var o2 = { name: 'world' }; function sayName() { alert(this.name); } sayName.call(this); // out sayName.call(window); // out sayName.call(o1); // hello sayName.call(o2); // world
前两个输出相同,因为在全局作用域,this即为window(浏览器环境)。
剩下的两个,我们分别改变了他们的执行环境,分别指向了o1和o2,于是结果就是显示对象各自的name值。
那么,使用call和apply有什么好处呢?我们发现,同样的一个函数,当指定不同的执行环境时,会产生不同的结果,这么做的一个最大的好处就是解耦。
使用call和apply,函数和对象没有强依赖关系,多个对象可以使用同一个函数,避免了资源的浪费,同时对于模块化编程也大有帮助。
如果你仍然对call和apply没有清晰的认识,可以试着这样理解。
我们把方法比作是工具,比如一把刀;而变量是具体的实物,比如一个苹果。我们可以使用这把刀切很多不同的苹果,在切苹果的过程中,实际上就是改变了刀的作用对象—不同的苹果。
在上面的例子
// 将类数组的对象转为数组 var arr = Array.prototype.slice.call(arguments);
slice是一个方法,但是它是属于Array对象prototype属性所有的,在对arguments使用时,我们可以理解为借用。
比如张三会砍树,即张三有砍树这个方法(至于张三有没有树无所谓),而李四有树,但他却不会砍,这时李四便可以借用张三砍树的方法来砍自己的树,写成代码就是
var zhangsan = { cut: function() { alert(this.tree); } }; var lisi = { tree: '杨树' }; zhangsan.cut.call(lisi); // alert('杨树')
还有一种情况是,李四自己也会砍树,但是有一天他病了,砍不动了,这时他也可以借用张三的砍树方法砍自己的树。在代码中就是
String.prototype.toString = function() { return 'shit'; // 所有的String的实例对象的toString方法都被污染了,只会输出'shit' }; var str = 'hello'; console.log(str.toString()); // 'shit' // 这时候怎么办呢? // 我们需要找一个没被污染的toString方法借来用一用,比如Object(或者Array等除了String的都可以) console.log(Object.prototype.toString.call(str)); // 输出正常的'[object String]'
到了这里,相信你对call和apply已经有了一个比较形象的认识了。以后再遇到类似的问题时,不妨想象成现实中的关系,可能困扰许久的问题就豁然开朗了。
call和apply另外一个应用就是函数的柯里化和反柯里化技术,有兴趣的可以看下面两篇文章:
http://sombie.diandian.com/post/2013-06-28/40050585369
http://www.alloyteam.com/2013/08/javascript-zhong-you-qu-di-fan-ke-li-hua-ji-shu/
3.call和apply的适用场景 来源大牛丁文森
call和apply的作用很简单,就是改变上下文,适用场景太多了,虽然有时候只是为了“美观”,下面几个是我常用的。
1.
Object.prototype.toString.call(Obj)
用来判断 Obj 的类型
arguments 虽然和Array 很像,但是他没有Array的push之类的方法,怎么办?
Array.prototype.push.call(arguments)
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(); });
相关文章推荐
- 【JavaScript 学习--12】--js 中两种函数定义的区别:函数声明和函数表达式
- javascript 函数声明和函数表达式的区别(学习笔记)
- javascript-函数声明和函数表达式-call-apply
- JavaScript学习笔记(十) 函数声明VS函数表达式
- java正则表达式学习总结,以及和javascript正则表达式的区别
- java正则表达式学习总结,以及和javascript正则表达式的区别
- JavaScript学习点滴 call、apply的区别
- JavaScript学习点滴 call、apply的区别
- javascript 函数声明与函数表达式的区别
- [ javascript ] javascript 函数声明与函数表达式的区别
- javascript 函数声明与函数表达式的区别介绍
- javascript 函数声明与函数表达式的区别介绍
- js学习之函数声明与函数表达式区别[原创]
- javascript 中的函数声明和函数表达式区别
- java正则表达式学习总结,以及和javascript正则表达式的区别
- js高级程序设计(第三版)总结--函数声明与函数表达式区别
- Javascript学习---函数内置方法call/apply
- javascript的执行顺序/函数声明和函数表达式的区别
- Javascript 函数声明和函数表达式的区别
- 详解Javascript 函数声明和函数表达式的区别