第一部分 基础知识
第2章 this 、 call 和 apply
2.1 this
JavaScript的 this 总是指向一个对象,而具体指向哪个对象是在运行时基于函数的执行环境动态绑定的,而非函数被声明时的环境。也就是说声明时不知道,运行时才知道。
this 的指向大致可以分为以下 4种:
作为对象的方法调用。
<script type="text/javascript"> //当函数作为对象的方法被调用时, this 指向该对象: var obj = { a:1, getA:function(){ console.log(this === obj); console.log(this.a); } } obj.getA(); </script>
作为普通函数调用。
<script> //作为普通函数调用 window.name = 'globalName'; var getName = function(){ return this.name; } console.log(getName()); var getId = function( id ){ return document.getElementById( id ); }; getId( 'div1' ); </script>
构造器调用。
<script> var MyClass = function(){ this.name = 'sven'; }; var obj = new MyClass(); alert ( obj.name ); // 输出:sven </script>
Function.prototype.call 或 Function.prototype.apply 调用。
<script> var obj1 = { name: 'sven', getName: function(){ return this.name; } }; var obj2 = { name: 'anne' }; console.log( obj1.getName() ); // 输出: sven console.log( obj1.getName.call( obj2 ) ); // 输出:anne </script>
2.2 call 和 apply
ECAMScript 3给 Function 的原型定义了两个方法,它们是 Function.prototype.call 和 Function.prototype.apply 。
2.2.1 call 和 apply 的区别
apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组, apply 方法把这个集合中的元素作为参数传递给被调用的函数。
2.2.2 call 和 apply 的用途
1. 改变 this 指向
<script> var obj1 = { name: 'sven' }; var obj2 = { name: 'anne' }; window.name = 'window'; var getName = function(){ alert ( this.name ); }; getName(); // 输出: window getName.call( obj1 ); // 输出: sven getName.call( obj2 ); // 输出: anne </script>
2. Function.prototype.bind
Function.prototype.bind = function(){ var self = this,// 保存原函数 context = [].shift.call(arguments);// 需要绑定的 this 上下文 args = [].slice.call(arguments);// 剩余的参数转成数组 // 返回一个新的函数 return function(){ // 执行新的函数的时候,会把之前传入的 context 当作新函数体内的 this // 并且组合两次分别传入的参数,作为新函数的参数 return self.apply(context, [].concat.call(args, [].slice.call(arguments))); } } var obj1 = { name:'john' }; var func1 = function(a,b,c,d){ console.log(this.name); console.log([a,b,c,d]); }.bind(obj1, 1,2); func1(3,4);
3. 借用其他对象的方法
第一种场景是“借用构造函数”
//借用构造函数 var A = functiono(name){ this.name = name; } var B = function(){ A.apply(this, arguments); } B.prototype.getName = function(){ return this.name; } var b = new B('john'); console.log(b.getName());
第二种场景借用 Array.prototype 对象上的方法
//借用其它对象 (function(){ Array.prototype.push.call(arguments, 3); console.log(arguments); })(1,2);