JavaScript为函数对象定义了两个方法:apply和call,它们的作用都是将函数绑定到另
外一个对象上去运行,两者仅在定义参数的方式有所区别:

Function.prototype.apply(thisArg,argArray);
Function.prototype.call(thisArg[,arg1[,arg2…]]);

从函数原型可以看到,第一个参数都被取名为thisArg,也就是说,所有函数内部的this
指针都会被赋值为thisArg,这就达到了将函数作为另外一个对象的方法运行的目的。两个
方法除了thisArg 参数,都是为Function 对象传递的参数。

 <script type="text/javascript">//定义一个函数func1,具有属性p和方法A
        function func1() {this.p = "func1-";this.A = function (arg) {alert(this.p + arg);}}//定义一个函数func2,具有属性p和方法B
        function func2() {this.p = "func2-";this.B = function (arg) {alert(this.p + arg);}}var obj1 = new func1();var obj2 = new func2();obj1.A("byA"); //显示func1-byAobj2.B("byB"); //显示func2-byBobj1.A.apply(obj2, ["byA"]); //显示func2-byA,其中[“byA”]是仅有一个元素的数组,下同obj2.B.apply(obj1, ["byB"]); //显示func1-byBobj1.A.call(obj2, "byA"); //显示func2-byAobj2.B.call(obj1, "byB"); //显示func1-byB</script>

可以看出,obj1的方法A被绑定到obj2运行后,整个函数A的运行环境就转移到了obj2,
即this指针指向了obj2。同样obj2 的函数B也可以绑定到obj1 对象去运行。代码的最后4
行显示了apply和call函数参数形式的区别。
与 arguments 的length属性不同,函数对象的还有一个参数相关的属性length,它表示
函数定义时所指定参数的个数,而非调用时实际传递的参数个数。例如下面的代码将显示2:

function sum(a,b){
return a+b;
}
alert(sum.length);

call,apply都是Function的原型的方法,其他function继承

this

和传统意义的面向对象的语言不同,JavaScript 中的this 指针是一个动态的变量,一个
方法内的this指针并不是始终指向定义该方法的对象的,在上一节讲函数的apply和call方
法时已经有过这样的例子。

 <script type="text/javascript"><!--//创建两个空对象var obj1 = new Object();var obj2 = new Object();//给两个对象都添加属性p,并分别等于1和2obj1.p = 1;obj2.p = 2;//给obj1添加方法,用于显示p的值obj1.getP = function () {alert(this.p); //表面上this指针指向的是obj1
        }//调用obj1的getP方法
        obj1.getP();//使obj2的getP方法等于obj1的getP方法obj2.getP = obj1.getP;//调用obj2的getP方法
        obj2.getP();
//--></script>

从代码的执行结果看,分别弹出对话框1 和2。由此可见,getP函数仅定义了一次,在
不同的场合运行,显示了不同的运行结果,这是有this指针的变化所决定的。在obj1 的getP
方法中,this就指向了obj1 对象,而在obj2 的getP 方法中,this就指向了obj2 对象,并通
过this指针引用到了两个对象都具有的属性p。
由此可见,JavaScript 中的this 指针是一个动态变化的变量,它表明了当前运行该函数
的对象。由this指针的性质,也可以更好的理解JavaScript中对象的本质:一个对象就是由
一个或多个属性(方法)组成的集合。每个集合元素不是仅能属于一个集合,而是可以动态
的属于多个集合。这样,一个方法(集合元素)由谁调用,this指针就指向谁。实际上,前
面介绍的apply方法和call方法都是通过强制改变this指针的值来实现的,使this指针指向
参数所指定的对象,从而达到将一个对象的方法作为另一个对象的方法运行的效果。

this的范围

var user={
name:"jack", //定义了name属性,初始化为jack
favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
hello:function(){ //定义了方法hello
alert("hello,"+this.name);
},
sex:"male" //定义了性别属性sex,初始化为sex
}
user.hello();       //"hello,jack"

var user={
name:"jack", //定义了name属性,初始化为jack
favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
hello:function(){ //定义了方法hello
alert("hello,"+name);
},
sex:"male" //定义了性别属性sex,初始化为sex
}
user.hello();      //"hello,"

name="hongda";
var user={
name:"jack", //定义了name属性,初始化为jack
favoriteColor:["red","green","black","white"],//定义了颜色喜好数组
hello:function(){ //定义了方法hello
alert("hello,"+name);
},
sex:"male" //定义了性别属性sex,初始化为sex
}
user.hello();          //"hello,hongda"

  name = "hongda";var user = {name: "jack", //定义了name属性,初始化为jackfavoriteColor: ["red", "green", "black", "white"], //定义了颜色喜好数组hello: function () { //定义了方法helloname = "hongdadada";alert("hello," + name);},sex: "male" //定义了性别属性sex,初始化为sex
        }user.hello();     //"hello,hongdadada"

一个对象内部的方法调用该对象的属性时要指明this,该属性不是某个范围内的变量。

 function fun() {name = "hongdada";function show() {  //没有意义alert(name);}}var f = new fun();console.dir(f);

 function fun() {this.name = "hongdada";this.show=function show() {alert(name);}}var f = new fun();console.dir(f);

function中没有this时,它就是个方法,只有有this时它才类似一个类

传递给函数的隐含参数:arguments

当进行函数调用时,除了指定的参数外,还创建一个隐含的对象——arguments。
arguments是一个类似数组但不是数组的对象,说它类似是因为它具有数组一样的访问性质,
可以用arguments[index]这样的语法取值,拥有数组长度属性length。arguments 对象存储的
是实际传递给函数的参数,而不只局限于函数声明所定义的参数列表,

function func(a,b){
alert(a);
alert(b);
for(var i=0;i<arguments.length;i++){
alert(arguments[i]);
}
}
func(1,2,3);   //1,2,1,2,3

代码:

 <script type="text/javascript">function dwn(s) {document.write(s + "<br/>");}//定义一个多边形(Polygon)类型
        function Polygon() {//存放多边形的顶点var m_points = [];m_points = Array.apply(m_points, arguments);//用上面介绍的那种方式定义getter
            function GETTER() { };GETTER.prototype = m_points[0];this.firstPoint = new GETTER();//公有属性this.length = {valueOf: function () { return m_points.length },toString: function () { return m_points.length }}//添加一个或多个顶点this.add = function () {m_points.push.apply(m_points, arguments);}//取得序号为idx 的顶点this.getPoint = function (idx) {return m_points[idx];}//设置特定需要的顶点this.setPoint = function (idx, point) {if (m_points[idx] == null) {m_points[idx] = point;}else {m_points[idx].x = point.x;m_points[idx].y = point.y;}}}//构造一个三角形pvar p = new Polygon({ x: 1, y: 2 }, { x: 2, y: 4 }, { x: 2, y: 6 });dwn(p.length);           //3dwn(p.firstPoint.x);     //1dwn(p.firstPoint.y);     //2p.firstPoint.x = 100; //不小心写了它的值dwn(p.getPoint(0).x); //1 不会影响到实际的私有成员delete p.firstPoint.x; //恢复dwn(p.firstPoint.x);    //1p.setPoint(0, { x: 3, y: 4 }); //通过setter 改写了实际的私有成员dwn(p.firstPoint.x); //3 getter 的值发生了改变dwn(p.getPoint(0).x);  //3</script>

应用例子:

 function dwn(s) {document.write(s + "<br/>");}function App() {var fun={};var arr = Array.apply(null, arguments);var arr2 = Array.apply(arr2, arguments);var arr3 = Array.apply(fun, arguments);var arr4 = Array.apply(window, arguments);dwn(arr);dwn(arr2);dwn(arr3);dwn(arr4);}App(1, 2, 3, 4, 5, 6, 7, 8);

Array这个function方法对象初始化中没有使用this,所有thisArg不管填什么都没影响。

   function Class1() {this.name = "class1";this.showNam = function () {alert(this.name);}}function Class2() {this.name = "class2";}var c1 = new Class1();var c2 = new Class2();c1.showNam.call(c2);    //class2

call也可以形成继承

   function Class1() {this.showTxt = function (txt) {alert(txt);}}function Class2() {Class1.call(this);}var c2 = new Class2();c2.showTxt("cc");     //cc

class2继承class1

多继承

function Class1() {this.showTxt1 = function (txt) {alert("Class1:"+txt);}}function Class0() {this.showTxt0 = function (txt) {alert("Class0:"+txt);}}function Class2() {Class0.call(this);Class1.call(this);}var c2 = new Class2();c2.showTxt0("cc");c2.showTxt1("cccc");

在javascript框架prototype里就使用apply来创建一个定义类的模式

var Class = {create: function() {return function() {this.initialize.apply(this, arguments);}}
}

解析:从代码看,该对象仅包含一个方法:Create,其返回一个函数,即类。但这也同时是类的
构造函数,其中调用initialize,而这个方法是在类创建时定义的初始化函数。通过如此途径,
就可以实现prototype中的类创建模式

  var vehicle=Class.create();vehicle.prototype = {initialize: function (type) {this.type = type;},showSelf: function () {alert("this vehicle is " + this.type);}}var moto=new vehicle("Moto");
moto.showSelf();

apply call this arguments caller callee相关推荐

  1. javascript下的arguments,caller,callee,call,apply示例及理解

    在看到大家如此关注JS里头的这几个对象,我试着把原文再修改一下,力求能再详细的阐明个中意义.在提到上述的概念之 前,首先想说说javascript中函数的隐含参数:arguments Argument ...

  2. JS报错-Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on...

    报错信息:Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on stric ...

  3. js中函数参数arguments、callee、caller,值传递、重载

    全栈工程师开发手册 (作者:栾鹏) js系列教程4-函数.函数参数教程全解 函数参数 arguments javascript中的函数定义并未指定函数形参的类型,函数调用也未对传入的实参值做任何类型检 ...

  4. 【转载】全面理解javascript的caller,callee,call,apply概念(修改版)

    今天写PPlayer,发现有段代码引起了我的兴趣: var Class = { create: function() { return function() { this.initialize.app ...

  5. js理解 call( ) | apply( ) | caller( ) | callee( )

    被js的这几个方法搞的this晕头转向,下定决心搞清楚: 1.call( )和apply( ):两者都可以将函数绑定到另外一个对象上去运行,只是参数的传递方式不同,两者都可以使当前函数拥有另一个对象的 ...

  6. js apply/call/caller/callee/bind使用方法与区别分析

    一.call 方法 调用一个对象的一个方法,以另一个对象替换当前对象(其实就是更改对象的内部指针,即改变对象的this指向的内容). Js代码 call([thisObj[,arg1[, arg2[, ...

  7. arguments,callee,caller

    arguments 定义函数时没有定义参数 如果实参数量大于形参时,使用arguments arguments只能出现在函数语句块中,不需要定义,直接使用. 用于当前函数的参数不固定数量. funct ...

  8. 关于arguments,caller以及匿名函数调用的问题

    此文内容不深,就当一个简单的笔记或总结吧. 先从arguments对象说起吧,[fnName.]arguments (其中fnName可选),为当前执行的 function 对象返回一个argumen ...

  9. javaScript(call,apply,date,arguments,Math)

    目录 call和apply this的情况 arguments Date对象 Math 包装类 字符串的相关方法 正则表达式 使用字面量来创建正则表达式 字符串和正则相关的方法 量词 练习 call和 ...

最新文章

  1. 1.mongodb在centos上面安装
  2. numpy.squeeze() 去除维度为1的向量
  3. 斯坦福CS231 BP后向传播
  4. Leetcode题目:House Robber II
  5. python 代理使用方法简介
  6. shell之实战应用一(查找xml文档中的关键字段)
  7. Error running ‘xxx‘: Command line is too long. Shorten command line for xxx or also for Spring Boot
  8. 官网安装Nvidia CUDA Toolkit、cuDNN报错502的备用镜像下载网址
  9. C++中的数组与指针
  10. 【Elasticsearch】Elasticsearch 5.1.2滚动升级至 5.6.4
  11. SQL Server超时诊断和调优
  12. 在Ubuntu上使用apt-get安装MySQL+安全优化
  13. 18.Linux软件安装之Rpm安装
  14. 《CSS世界》(张鑫旭)pdf
  15. 什么是TCP粘包?怎么解决TCP粘包问题?
  16. 嵌入式开发Linux入门
  17. 教程篇(7.0) 03. FortiGate安全 防火墙策略 ❀ Fortinet 网络安全专家 NSE 4
  18. python之代码可读性浅谈
  19. 云端IDE:阿里云机器学习与PAI-DSW | 《阿里云机器学习PAI-DSW入门指南》
  20. 编写一个简单的javaweb网上商城项目

热门文章

  1. 解决 Virtual PC 在 XP PAE模式下无法运行的问题
  2. Unity中GameObject API解析
  3. ionic3相关知识收集
  4. SoapUI实践:自动化测试、压力测试、持续集成
  5. 如何卸载挂载的共享文件夹
  6. Android Studio 使用Gradle引入第三方库文件的总结
  7. 【撸码师的读书笔记】 深入理解Java虚拟机——JVM高级特性与最佳实践
  8. 程序员没有天才:暴风影音首席架构师鲍金龙访谈
  9. Bitmap的一个简单实现
  10. iis6中FTP配置的技巧和细节