日期:2014-05-16  浏览次数:20309 次

关于Javascript中call与apply的进一步探讨

我一直认为代码是最能说明问题的.必要的地方我写有注释.参考一些相关的文章.下面的代码做了进一步的探讨.或许能让理解call和apply更进一步!

?

			function log(a) {
				//我习惯使用firebug和chrome自己的调试器.您也可以手动修改为alert
				console.log(a);
			}

			function ObjB() {
				this.message = "messageB";
				this.setMessage = function(arg) {
					this.message = arg;
				};
			}

			function ObjA() {
				this.message = "messageA";
				this.getMessage = function() {
					return this.message;
				};
			}

			var b = new ObjB();
			var a = new ObjA();
			//可以直接访问属性.输出为messageA
			log(a.message);

			//给对象ObjA动态指派ObjB的setMessage方法,注意,ObjA本身是没有这方法的!
			b.setMessage.call(a, "A的消息");
			//输出"A的消息"
			log(a.getMessage());
			//给对象b动态指派a的getMessage方法,注意,b本身也是没有这方法的!可以理解为得到A里面的getMessage方法体.然后用call注入到B里面执行.因为上下文变成了B,所以B多了getMessage方法体.
			var result = a.getMessage.call(b);
			//输出"messageB"
			log(result);
			//Uncaught TypeError: Object #<ObjB> has no method 'getMessage' 出错了.因为call并没有把getMessage永久注入进ObjB
			//log(b.getMessage());

			function print(a, b, c, d) {
				log("调用者是:" + arguments.callee.caller.name + " 上下文是:" + this + "  参数是:" + a + b + c + d);
			}

			//通过example里面 的三次调用,可以看出:call, apply方法区别是,从第二个参数起, call方法参数将依次传递给借用的方法作参数, 而apply直接将这些参数放到一个数组中再传递, 最后借用方法的参数列表是一样的.
			function example1(a, b, c, d) {
				//用call方式借用print,参数次序传递.
				print.call(this, a, b, c, d);
				//用apply方式借用print, 参数作为一个数组传递,
				//这里直接用JavaScript方法内本身有的arguments数组
				print.apply(this, arguments);
				//或者封装成数组
				print.apply(this, [a, b, c, d]);
			}

			//此方法和example1一样.但是突出分析this代表什么东西.
			function example2(a, b, c, d) {
				print.call(window, a, b, c, d);
				print.apply(window, arguments);
				print.apply(window, [a, b, c, d]);
			}

			example1("参数1", "参数2", "参数3", "参数4");
			example2("参数1", "参数2", "参数3", "参数4");

			/* -----------------------------*/
			function SimulateFun() {
				this.print = function(a, b, c, d) {
					log("调用者是:" + arguments.callee.caller.name + " 上下文是:" + this + "  参数是:" + a + b + c + d);
				}
			}

			var simulateFun = new SimulateFun();
			function example3(a, b, c, d) {
				simulateFun.print.call(this, a, b, c, d);
				simulateFun.print.apply(this, arguments);
				simulateFun.print.apply(this, [a, b, c, d]);
			}

			example3("参数1", "参数2", "参数3", "参数4");

			/* -----------------------------*/
			function ContentSimulate() {
				this.example4 = function example4(a, b, c, d) {
					simulateFun.print.call(this, a, b, c, d);
					simulateFun.print.apply(this, arguments);
					simulateFun.print.apply(this, [a, b, c, d]);
				}
				this.example5 = function example5(a, b, c, d) {
					print.call(this, a, b, c, d);
					print.apply(this, arguments);
					print.apply(this, [a, b, c, d]);
				}
			}

			var contentSimulate = new ContentSimulate();
			//这里的上下文变成了ContentSimulate对象
			contentSimulate.example4("参数1", "参数2", "参数3", "参数4");
			//这里的上下文变成了ContentSimulate对象
			contentSimulate.example5("参数1", "参数2", "参数3", "参数4");
?