学习js,需要将多个知识点结合起来看,因为js中很多特点或技巧都是有几个基本的属性和方法组合而来的,就比如本文中的new和bind(),其实就是由this+call() | apply() (等同于)组合而来的。下面进入正题:
一、this
function wrap(){ f(); //1 var ff = new f(); //2 function f(){ console.log(this); }; var o = { p:function(){console.log(this);}, q:function(){ r(); function r(){console.log(this);} } }; o.p(); //3 o.q(); //4 var g = function(){ console.log(this) }; g(); //5 //6 (function(){ console.log(this); }()); } wrap();
由此可以看出,this指向的是一个对象字面量。( 虽然函数也是一种特殊的对象,但它的存在的意义是执行操作,而对象字面量则仅限于对某一类东西进行描述。)
判断js中this的指向问题,可以这样:找到被调用的位置,如果是对象的属性,那么this就指向该对象;如果是在函数内部,或者在全局环境下,那么this指向的是window对象;apply()、call()、bind()另算。
【注:在严格模式下,未指定环境对象而调用函数,并且没有使用apply()或call(),那么this值为undefined】
二、js中能够修改this的方法有两种 : apply() , call() ;
1. apply() :
x.apply(this,arguments) 【将后者数组中的元素一个个添加到前面的对象中,这里就是将当前函数的参数全部添加到this中】
x.apply(this,[arr1,arr2]);
{
应用技巧:
1、数组的添加
var
arr1 = [12 ,
"foo"
, {name
"Joe"
} , -2458];
var
arry2 = [
"Doe"
, 100];
Array.prototype.push.apply(arr1, arr2); //此时的arr1 值为 [12 , "foo" , {name "Joe"} , -2458 , "Doe" , 100]
var
num = [5, 458 , 120 , -215 ];
var
maxNum = Math.max.apply(Math, num),
//458
maxNum = Math.max.call(Math,5, 458 , 120 , -215);
//458
}
2. call() :
x.call(this,arr1,arr2,arr3); 【必须明确的传入每一个参数】
apply和call还可以利用对象和方法之间没有任何耦合关系的这一特征,来实现作用域的切换。
【关于apply()和call()方法,有篇文章解释的很详细:点击这里 】
三、在方法apply()和call()的基础上,还能实现其它的功能,比如new、bind() 方法:
new:
var
obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
bind():
Function.prototype.bind = function(){
var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
return function(){
return fn.apply(object,
args.concat(Array.prototype.slice.call(arguments)));
};
};
【call和apply都是对函数的直接调用,而bind方法返回的仍然是一个函数】
四、构造函数(this的具体应用)
构造函数的过程中也会应用到this,所谓构造函数,实际上就是创建了一个新的对象,然后把所有属性和操作在这新的环境下执行。
在实际执行过程中一般分为两种,一种是先给函数中的属性赋值,然后用new方法实现:
function test(){
this.a=10;
return function(){
return 1; // do something
}
}
var m=new test();
另一种是类似jQuery,把new方法写在函数中:
(让人惊叹的是jQuery中的构造的方式是可以链式编程的,原理其实相当于用一个新的函数对象(即构造函数对象)替换之,而公共的prototype部分不变。)
z = function() {
return new z.fn.init();
};
z.fn=z.prototype = {
constructor: z,
init:function() {
return this;
}
}
【
补充总结:
1、this一旦确定,便无法修改,在函数内会报错
2、this代表了调用者对象的作用范围,这样就可以通过this来给被调用的对象添加或修改属性
3、基于2,apply和call方法则是相当于导入了当前作用域相对应的对象
】