用call和apply区别和call怎么继承原型链上的共享属性

编程开发子分类js继承call()和apply()方法总结
投稿:hebedich
字体:[ ] 类型:转载 时间:
本文介绍了js继承当中的call和apply方法,从定义到常用实例都做了分析,非常的实用,推荐给小伙伴们。
1、方法定义
语法:call([thisObj[,arg1[, arg2[,&& [,.argN]]]]])
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
apply方法:
语法:apply([thisObj[,argArray]])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
2、常用实例
function add(a,b)&
&&& alert(a+b);&
function sub(a,b)&
&&& alert(a-b);&
add.call(sub,3,1);&&
&这个例子中的意思就是用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4); // 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。
function Animal(){&&&
&&& this.name = "Animal";&&&
&&& this.showName = function(){&&&
&&&&&&& alert(this.name);&&&
function Cat(){&&&
&&& this.name = "Cat";&&&
var animal = new Animal();&&&
var cat = new Cat();&&&
//通过call或apply方法,将原本属于Animal对象的showName()方法交给对象cat来使用了。&&&
//输入结果为"Cat"&&&
animal.showName.call(cat,",");&&&
//animal.showName.apply(cat,[]);&
&call 的意思是把 animal 的方法放到cat上执行,原来cat是没有showName() 方法,现在是把animal 的showName()方法放到 cat上来执行,所以this.name 应该是 Cat
c、实现继承
function Animal(name){&&&&&
&&& this.name =&&&&&
&&& this.showName = function(){&&&&&
&&&&&&& alert(this.name);&&&&&
&&& }&&&&&
function Cat(name){&&&
&&& Animal.call(this, name);&&&
var cat = new Cat("Black Cat");&&&&
cat.showName();&
&Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么 Cat中不就有Animal的所有属性和方法了吗,Cat对象就能够直接调用Animal的方法以及属性了.
d、多重继承
function Class10()&
&&& this.showSub = function(a,b)&
&&&&&&& alert(a-b);&
function Class11()&
&&& this.showAdd = function(a,b)&
&&&&&&& alert(a+b);&
function Class2()&
&&& Class10.call(this);&
&&& Class11.call(this);&
&很简单,使用两个 call 就实现多重继承了
当然,js的继承还有其他方法,例如使用原型链,这个不属于本文的范畴,只是在此说明call 的用法。说了call ,当然还有 apply,这两个方法基本上是一个意思,区别在于 call 的第二个参数可以是任意类型,而apply的第二个参数必须是数组,也可以是arguments
还有 callee,caller..
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具Javascript中的apply和call继承 - 博客频道 - CSDN.NET
平凡,追赶
分类:前端
call实现继承
call这里call的意思就是把animal的方法应用到cat这个对象身上,也就是animal的属性创建到了cat里面,所以cat就继承了animal的方法
function animal(a, b) {
this.type = 'animal'
this.behavior = function(){
console.log(this.type+" is running")
function cat(a, b) {
this.name = 'wsscat'
animal.call(this);
console.log(new cat())
call实现多重继承
当然我们可以继承多个构造函数,这就是多重继承
function animal(a, b) {
this.type = 'animal'
this.behavior = function(){
console.log(this.type+" is running")
function wsscat(a, b) {
this.age = 0
function cat(a, b) {
this.name = 'wsscat'
animal.call(this);
wsscat.call(this);
console.log(new cat())
只要在cat的构造函数中有多个call就可以,此时的cat继承了wsscat和animal
apply和call的区别
其实apply和call这两个方法基本上是差不多的,区别在于call的第二个参数可以是任意类型,而apply的第二个参数必须是数组,也可以是arguments(即传给构造函数的参数)
例如我们把上面的代码稍微改一下,如果此时我在new构造函数cat的时候传入参数new cat('wsscat','cute')我们的cat能接收arguments,但是如果此时继承是animal.call(this),没有给call传第二个参数的时候,生成的对象中type的值就会是undefined,所以为了让这个值能够让animal接收,我们可以在animal中传入第二个参数animal.call(this,type)
function animal(type) {
this.type = type
this.behavior = function(){
console.log(this.type+" is running")
function cat(name, type) {
this.name = name
animal.apply(this,arguments)
console.log(new cat('wsscat','cute'))
这里用apply就很方便,因为arguments是数组,可以全部传给animal,而call就要一个个地传过去
animal.call(this);//type undefined
animal.call(this,type);//type cute
animal.call(this,arguments[1]);//type cute
animal.call(this,arguments);//type [‘wsscat’,’cute’]
animal.apply(this,arguments)//type: wsscat
继承的优化
如果构造函数this绑定太多属性(比如一些共同方法),在实例化后会造成浪费,为此我们一般会使用原型链来优化,但是使用原型链之后我们的apply和call的继承方法就会失效
为此我们一般使用混合的写法,使用原型链和(apply或者call)方法进行继承
具体两句话
让子的原型链指向父的实例(父实例化的对象)
cat.prototype = new animal();
让父的属性创建在子的this上
animal.call(this, type)
整体代码如下,那么就会让父原型链的属性和this上的属性都得到继承
function animal(type) {
this.type = type
this.behavior = function() {
console.log(this.type + " is running")
animal.prototype.action = function() {
console.log("running")
function cat(name, type) {
this.name = name
animal.call(this, type)
cat.prototype = new animal();
console.log(new cat('wsscat', 'cute'));
(new cat('wsscat')).action()
排名:第5136名
(40)(1)(8)(1)(4)(4)(7)(2)(5)(0)(4)(0)(0)如何理解和熟练运用js中的call及apply?
有时候看一两个关于apply或call的小例子,感觉能够理解一点点但是下次碰到又要纠结半天才能转过弯来~而且不知道怎么应用到实际工作当中去~
LZ要先明白存在call和apply的原因,才能记得牢一点:
在javascript OOP中,我们经常会这样定义:
function cat(){}cat.prototype={
food:"fish",
say: function(){
alert("I love "+this.food);
}}var blackCat =blackCat.say(); 但是如果我们有一个对象whiteDog = {food:"bone"},我们不想对它重新定义say方法,那么我们可以通过call或apply用blackCat的say方法:blackCat.say.call(whiteDog);所以,可以看出call和apply是为了动态改变this而出现的,当一个object没有某个方法,但是其他的有,我们可以借助call或apply用其它对象的方法来操作。用的比较多的,通过document.getElementsByTagName选择的dom 节点是一种类似array的array。它不能应用Array下的push,pop等方法。我们可以通过:var domNodes =
Array.prototype.slice.call(document.getElementsByTagName("*"));这样domNodes就可以应用Array下的所有方法了。其他的就不提了,讲多了反而迷惑。
call 和 apply 都是为了改变某个函数运行时的 context 即上下文而存在的,换句话说,就是为了改变函数体内部 this 的指向。因为 JavaScript 的函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。二者的作用完全一样,只是接受参数的方式不太一样。例如,有一个函数 func1 定义如下:var func1 = function(arg1, arg2) {};就可以通过 func1.call(this, arg1, arg2); 或者 func1.apply(this, [arg1, arg2]); 来调用。其中 this 是你想指定的上下文,他可以任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时,用 call,而不确定的时候,用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来便利所有的参数。
函数调用的三种方式:obj.myFunc();myFunc.call(obj,arg);myFunc.apply(obj,[arg1,arg2..]);
apply: call:NOTE: While the syntax of this function is almost identical to that of call(), the fundamental difference is that call() accepts an argument list, while apply() accepts a single array of arguments. call 和 apply 的区别只在于这两个函数接受的参数形式不同。Example: 判断一个变量是不是Arrayvar a = {};var b = []Object.prototype.toString.call(a);
// 输出为: "[object Object]" Object.prototype.toString.call(a);
// 输出为: "[object Array]" update: 使用call和apply方法,可以改变对象方法的运行环境,例如,有一个类Manfunction Man() {}
Man.prototype = {
valet: false,
wakeUp: function(event) {
console.log(this.valet + "? Some breakfase, please.");
//get "undefined? Some breakfast, please
var button = document.getElementById('morning');
button.addEventListener(
wooster.wakeUp,
//使用apply来改变 wakeUp 的上下文环境,即 wakeUp 中的this
var button = document.getElementById('morning2');
button.addEventListener(
function() {
Man.prototype.wakeUp.apply(wooster, arguments);
ps:以上代码例子来自与《深入Ajax架构与最佳实践》3.1 对象与事件触发
JS functions are objects JS函数是对象,没什么特别的... that have .call and .apply methods 这些对象只不过有call和apply两个特别的方法而已... both take an object as the first argument call和apply的第一个参数是任一个对象... which specifies the target where the function runs against 既函数的执行(作用)目标function fn (a) { ... }
var obj = { ... }
// 在obj上执行fn
fn.call(obj, ...)
fn.apply(obj, ....)
obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
两者作用一致,都是把obj(即this)绑定到thisObj,这时候thisObj具备了obj的属性和方法。或者说thisObj『继承』了obj的属性和方法。唯一区别是apply接受的是数组参数,call接受的是连续参数。function add(j, k){
return j+k;
function sub(j, k){
return j-k;
我们在控制台运行:add(5,3); //8
add.call(sub, 5, 3); //8
add.apply(sub, [5, 3]); //8
sub(5, 3); //2
sub.call(add, 5, 3); //2
sub.apply(add, [5, 3]); //2
通过call和apply,我们可以实现对象继承。示例:var Parent = function(){
this.name = "yjc";
this.age = 22;
var child = {};
console.log(child);//Object {} ,空对象
Parent.call(child);
console.log(child); //Object {name: "yjc", age: 22}
以上实现了对象的继承。更多阅读:js笔记——call,apply,bind使用笔记 - 飞鸿影~ - 博客园
我也是刚刚理解,你首先要知道call和apply是Function的方法,他的第一个参数是this,第二个是Function的参数。比如你的方法里写了this,普通调用这个方法这个this可能是window。而如果你用了call,第一个参数写啥,里面的this就是啥
其实就是动态的改变this了,下面例子就说明了。。。
function add(a, b){console.dir(this);}
function sub(a, b){console.dir(this);}
add.call(sub, 1, 2);
"sub(a, b)"
sub.apply(add, [1, 2]);
"add(a, b)"
call和apply可以用来重新定义函数的执行环境,也就是this的指向。通过一个操作DOM的例子来理解。function changeStyle(attr, value){
this.style[attr] =
var box = document.getElementById('box');
window.changeStyle.call(box, "height", "200px");
call中的第一个参数用于指定将要调用此函数的对象,在这里,changeStyle函数将被box对象调用,this指向了box对象,如果不用call的话,程序报错,因为window对象中没有style属性。apply的用法:window.changeStyle.apply(box, ['height', '200px']);
你首先要明白 this 是个参数,然后就好理解了:普通的函数调用隐式传入 this,call 和 apply 可以显式指定它。简单方法调用的小步语义......
已有帐号?
无法登录?
社交帐号登录js中继承的几种用法总结(apply,call,prototype)
字体:[ ] 类型:转载 时间:
本篇文章主要介绍了js中继承的几种用法总结(apply,call,prototype) 需要的朋友可以过来参考下,希望对大家有所帮助
一,js中对象继承
js中有三种继承方式
1.js原型(prototype)实现继承 代码如下:&SPAN style="BACKGROUND-COLOR: #ffffff"&&SPAN style="FONT-SIZE: 18px"&&html&& &body&& &script type="text/javascript"&& &&& function Person(name,age){& &&&&&&& this.name=& &&&&&&& this.age=& &&& }& &&& Person.prototype.sayHello=function(){& &&&&&&& alert("使用原型得到Name:"+this.name);& &&& }& &&& var per=new Person("马小倩",21);& &&& per.sayHello(); //输出:使用原型得到Name:马小倩& &&&&& &&& function Student(){}& &&& Student.prototype=new Person("洪如彤",21);& &&& var stu=new Student();& &&& Student.prototype.grade=5;& &&& Student.prototype.intr=function(){& &&&&&&& alert(this.grade);& &&& }& &&& stu.sayHello();//输出:使用原型得到Name:洪如彤& &&& stu.intr();//输出:5& &/script&& &/body&& &/html&&/SPAN&&/SPAN&& 2.构造函数实现继承 代码如下:&SPAN style="FONT-SIZE: 18px"&&html&& &body&& &script type="text/javascript"&& &&& function& Parent(name){& &&&&&&& this.name=& &&&&&&& this.sayParent=function(){& &&&&&&&&&&& alert("Parent:"+this.name);& &&&&&&& }& &&& }& &&& function& Child(name,age){& &&&&&&& this.tempMethod=P& &&&&&&& this.tempMethod(name);& &&&&&&& this.age=& &&&&&&& this.sayChild=function(){& &&&&&&&&&&& alert("Child:"+this.name+"age:"+this.age);& &&&&&&& }& &&& }& &&& var parent=new Parent("江剑臣");& &&& parent.sayParent(); //输出:“Parent:江剑臣”& &&& var child=new Child("李鸣",24); //输出:“Child:李鸣 age:24”& &&& child.sayChild();& &/script&& &/body&& &/html&&/SPAN& 3.call , apply实现继承 代码如下:&SPAN style="FONT-SIZE: 18px"&&html&& &body&& &script type="text/javascript"&& &&& function& Person(name,age,love){& &&&&&&& this.name=& &&&&&&& this.age=& &&&&&&& this.love=& &&&&&&& this.say=function say(){& &&&&&&&&&&& alert("姓名:"+name);& &&&&&&& }& &&& }& &&& //call方式& &&& function student(name,age){& &&&&&&& Person.call(this,name,age);& &&& }& &&& //apply方式& &&& function teacher(name,love){& &&&&&&& Person.apply(this,[name,love]);& &&&&&&& //Person.apply(this,arguments); //跟上句一样的效果,arguments& &&& }& &&& //call与aplly的异同:& &&& //1,第一个参数this都一样,指当前对象& &&& //2,第二个参数不一样:call的是一个个的参数列表;apply的是一个数组(arguments也可以)& &&& var per=new Person("武凤楼",25,"魏荧屏"); //输出:“武凤楼”& &&& per.say();& &&& var stu=new student("曹玉",18);//输出:“曹玉”& &&& stu.say();& &&& var tea=new teacher("秦杰",16);//输出:“秦杰”& &&& tea.say();& &/script&& &/body&& &/html&&/SPAN&& 二、call和apply的用法(详细介绍)
js中call和apply都可以实现继承,唯一的一点参数不同,func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])。
JS手册中对call的解释: 代码如下:&SPAN style="FONT-SIZE: 18px"&call 方法& 调用一个对象的一个方法,以另一个对象替换当前对象。& &&& call([thisObj[,arg1[, arg2[,&& [,.argN]]]]])& 参数& thisObj& 可选项。将被用作当前对象的对象。& arg1, arg2,& , argN& 可选项。将被传递方法参数序列。& 说明& call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。& 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。&/SPAN&& 说简单一点,这两函数的作用其实就是更改对象的内部指针,即改变对象的this指向的内容。这在面向对象的js编程过程中有时是很有用的。下面以apply为例,说说这两个函数在 js中的重要作用。如: 代码如下:&SPAN style="FONT-SIZE: 18px"& function Person(name,age){&& //定义一个类&& &&&&&&& this.name=&&&& //名字&& &&&&&&& this.age=&&&&&& //年龄&& &&&&&&& this.sayhello=function(){alert(this.name)};& &&& }& &&& function Print(){&&&&&&&&&&& //显示类的属性&& &&&&&&& this.funcName="Print";& &&&&&&& this.show=function(){& &&&&&&&&&&& var msg=[];& &&&&&&&&&&& for(var key in this){& &&&&&&&&&&&&&&& if(typeof(this[key])!="function"){& &&&&&&&&&&&&&&&&&&& msg.push([key,":",this[key]].join(""));& &&&&&&&&&&&&&&& }& &&&&&&&&&&& }& &&&&&&&&&&& alert(msg.join(" "));& &&&&&&& };& &&& }& &&& function Student(name,age,grade,school){&&& //学生类&& &&&&&&& Person.apply(this,arguments);//比call优越的地方&& &&&&&&& Print.apply(this,arguments);& &&&&&&& this.grade=&&&&&&&&&&&&&&& //年级&& &&&&&&& this.school=&&&&&&&&&&&&&&&& //学校&& &&& }& &&& var p1=new Person("卜开化",80);& &&& p1.sayhello();& &&& var s1=new Student("白云飞",40,9,"岳麓书院");& &&& s1.show();& &&& s1.sayhello();& &&& alert(s1.funcName);&/SPAN&& 另外,Function.apply()在提升程序性能方面有着突出的作用:我们先从Math.max()函数说起,Math.max后面可以接任意个参数,最后返回所有参数中的最大值。比如 代码如下:&SPAN style="FONT-SIZE: 18px"&alert(Math.max(5,8));&& //8&& &&& alert(Math.max(5,7,9,3,1,6));&& //9&& &&& //但是在很多情况下,我们需要找出数组中最大的元素。&& &&& var arr=[5,7,9,1];& &&& //alert(Math.max(arr));&&& // 这样却是不行的。NaN&& &&& //要这样写&& &&& function getMax(arr){& &&&&&&& var arrLen=arr.& &&&&&&& for(var i=0,ret=arr[0];i&arrLi++){& &&&&&&&&&&& ret=Math.max(ret,arr[i]);& &&&&&&& }& &&&&&&&& &&& }& &&& alert(getMax(arr)); //9&& &&& //换用apply,可以这样写&& &&& function getMax2(arr){& &&&&&&& return Math.max.apply(null,arr);& &&& }& &&& alert(getMax2(arr)); //9&& &&& //两段代码达到了同样的目的,但是getMax2却优雅,高效,简洁得多。&& &&& //再比如数组的push方法。&& &&& var arr1=[1,3,4];& &&& var arr2=[3,4,5];& &&& //如果我们要把 arr2展开,然后一个一个追加到arr1中去,最后让arr1=[1,3,4,3,4,5]&& &&& //arr1.push(arr2)显然是不行的。 因为这样做会得到[1,3,4,[3,4,5]]&& &&& //我们只能用一个循环去一个一个的push(当然也可以用arr1.concat(arr2),但是concat方法并不改变arr1本身)&& &&& var arrLen=arr2.& &&& for(var i=0;i&arrLi++){& &&&&&&& arr1.push(arr2[i]);& &&& }& &&& //自从有了Apply,事情就变得如此简单&& &&& Array.prototype.push.apply(arr1,arr2); //现在arr1就是想要的结果&/SPAN&&
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具

我要回帖

更多关于 call和apply区别 的文章

 

随机推荐