调用 this用法
this是函数体内自带的一个对象指针,它始终指向调用对象。当函数被调用时,使用this可以访问调用对象。this关键字的使用范围局限于函数体内或者调用范围。具体用法:
this[.属性]
如果this未包含属性,则传递的是当前对象。
this的用法比较灵活,它可以存在于任何位置,它不仅仅局限于对象的方法内,还可以被应用在全局域内,函数内,以及其他特殊上下文环境中。
- 函数的引用和调用
函数的引用和调用分别是不同的概念。虽然它们都无法改变函数的定义作用域。但是引用函数却能够改变函数的执行作用域,而调用函数是不会改变函数的执行作用域的。
var o={
name:"对象o",
f:function(){
return this;
}
}
o.O1={
name:"对象o1",
me:o.f //引用对象o的方法f
}
var who=o.O1.me();
alert(who.name);
var o={
name:"对象o",
f:function(){
return this;
}
}
o.O1={
name:"对象o1",
me:o.f() //调用对象o的方法f
}
var who=o.O1.me;
alert(who.name);
- 使用call()和apply()
call()和apply()方法可以直接改变被执行函数的作用域,使其作用域指向所传递的参数对象。因此函数中包含的this关键字也指向参数对象。
call()方法可以把函数强制转换对象的一个方法并执行。
function f(){
if(this.constructor==arguments.callee){
alert("this=实例对象");
}else if(this==window){
alert("this=window对象");
}else{
alert("this==其他对象 \n this.constructor="+this.constructor);
}
}
f();
直接调用函数f()时,函数执行作用域为全局域,所以this代表window。
new f();
当使用new运算符调用函数时,将创建一个新的实例对象,函数的执行作用域为实例对象所在的上下文,作用this就指向这个新创建的实例对象。
f.call(1);
使用call()方法执行函数f()时,call会把函数f()作用域强制修改为参数对象所在的上下文。
function f(){
alert(this.x+this.y);
}
var o={
x:1,
y:2
}
f.call(o);
call()方法吧函数f()强制转换为对象o的一个方法并执行,这样函数f()中的this就指代对象o。
- 原型继承
JavaScript通过原型模式实现类的延续和继承,如果在父类的成员中包含了this关键字,当子类继承了父类的这些成员时,this会指向子类的实例对象,但是也可以指向子类的原型对象,而不是子类的实例对象。
function Base(){ //基类
this.m=function(){
return "Base";
};
this.a=this.m();
this.b=this.m;
this.c=function(){
return this.m();
}
}
function F(){ //子类
this.m=function(){
return "F";
}
}
F.prototype=new Base();
var f=new F();
alert(f.a);
alert(f.b());
alert(f.c());
为父类定义私有函数,然后再把它的引用传递给其他父类成员,这样可避免因为函数闭包的原因,而改变this的值。
function Base(){
var m=function(){
return "Base";
};
this.a=m();
this.b=m;
}
function F(){
this.m=function(){
return "F";
}
}
F.prototype=new Base();
var f=new F();
alert(f.a); // 返回“Base”
alert(f.b());// 返回“Base”
- 异步调用事件之事件处理函数
异步调用就是通过事件机制或者计时器来延迟函数的调用时间和时机。通过调用函数的执行作用域不再是原来的定义作用域,所有函数中的this总是指向引发该事件的对象。
<input type="button" value="Button"/>
var button=document.getElementsByTagName("input")[0];
var o={};
o.f=function(){
if(this==o){
alert("this=o");
}
if(this==window){
alert("this==window");
}
if(this==button){
alert("this=button");
}
}
button.onclick=o.f;
- 异步调用之定时器
定时器就是指调用window对象的setTimeout()或setInterval()方法来延期调用函数。
var o={};
o.f=function(){
if(this==o){
alert("this=o");
}
if(this==window){
alert("this==window");
}
if(this==button){
alert("this=button");
}
}
setTimeout(o.f,100);
setTimeout(function(){
o.f.call(o);
},100);
this安全策略
this的复杂性很大程度上取决于用户的使用方式。
- 把this作为参数值来传递。
<input type="button" value="按钮1" onclick="f(this)"/>
<input type="button" value="按钮2" onclick="f(this)"/>
<input type="button" value="按钮3" onclick="f(this)"/>
function f(o){
alert(o.value);
}
- 设计静态this指针。
如果要确保构造函数的方法在初始化之后方法所包含的this指针不再发生变化,一个简单的方法就是:在构造函数中把this指针存储在私有变量中,然后在方法中使用私有变量来引用this指针,这样所引用的对象始终都是初始化的实例对象,而不会在类型继承中发生变化。
function Base(){
var _this=this;
this.m=function(){
return _this;
};
this.name="Base";
}
function F(){
this.name="F";
}
F.prototype=new Base();
var f=new F();
var n=f.m();
alert(n.name);
var o={
name:"this=o",
b:function(){
return o;
}
}
var o1={
name:"this=o1",
b:o.b
}
var a=o1.b();
alert(a.name);
</script>
- 设计静态的this扩展方法。
为Function对象扩展一个原型方法pointTo()
Function.prototype.pointTo=function(o){
var _this=this; // 存储当前函数对象
return function(){ //返回一个闭包函数
return _this.apply(o,arguments);
//返回执行当前函数,并把当前函数的作用域强制设置为指定对象。
}
}
利用函数的扩展方法,以实现强制指定对象o的方法b()中的this始终指向定义对象o。
var o={
name:"this=o"
}
o.b=(function(){
return this;
}).pointTo(o);
var o1={
name:"this=o1",
b:o.b
}
var a=o1.b();
alert(a.name);
function instanceFrom(f){
var a=[].slice.call(arguments,1); //获取构造函数的参数
f.prototype.constructor=f;
f.apply(f.prototype,a);
return f.prototype;
}
function F(){
this.name="F";
}
var f=instanceFrom(F);
alert(f.name);
应用this
例子1
function f(){
this.x=function(x){
return x*x;
}
}
f();
alert(window.x(6));
例子2-使用new运算符调用函数
function f(){
this.x=function(x){
return x*x;
}
}
var a=new f();
alert(a.x(6));
例子3-利用this可以调用对象定义属性
var x=2;
function f(){
this.x=20;
}
alert(x);
var x=2;
function f(){
this.x=20;
}
f();
alert(x);
例子4-在全局作用域,所有变量和函数的调用对象都是window。
window.x=2;
function f(){
this.x=20;
}
window.f();
alert(window.x);
例子5-先调用isNaN()方法,然后在函数体f体内使用this重写isNaN()方法,在全局作用域内调用函数f,然后再调用isNaN()方法,则返回值永远是false。
alert(isNaN(NaN)); //true
function f(){
this.isNaN=function(){
return false;
};
}
f();
alert(isNaN(NaN)); //false
例子6-嵌套函数结构体内this的变化规律
function f(){
this.a=" a ";
alert(this.a+this.b+this.c+this.d); //a undefinedundefinedundefined
e();
function e(){
this.b=" b ";
alert(this.a+this.b+this.c+this.d);//a b undefinedundefined
g();
function g(){
this.c=" c ";
alert(this.a+this.b+this.c+this.d);//a b c undefined
h();
function h(){
this.d=" d ";
alert(this.a+this.b+this.c+this.d); //a b c d
}
}
}
}
f();
例子7
function f(){
this.a=" a ";
alert(this.a+this.b+this.c+this.d);
var x=new e();
function e(){
this.b=" b ";
alert(this.a+this.b+this.c+this.d);
var x=new g();
function g(){
this.c=" c ";
alert(this.a+this.b+this.c+this.d);
var x=new h();
function h(){
this.d=" d ";
alert(this.a+this.b+this.c+this.d);
}
}
}
}
var x=new f();
函数调用模式
在JavaScript中,共有4中函数调用模式。
- 方法调用模式
当一个函数被保存为对象的一个属性值时,将称之为一个方法。当一个方法被调用时,this被绑定到当前对象。
var obj={
value:0,
increment:function(inc){
this.value+=typeof inc ==='number'?inc:1;
}
}
obj.increment();
document.write(obj.value); //1
obj.increment(2);
document.write(obj.value); //3
- 函数调用模式
当一个函数不是一个对象的属性时,它将被当作一个函数来调用。
var obj={
value:3,
doub:function(){
var that=this;
var helper=function(){
that.value=that.value*2;
};
helper();
}
}
obj.doub();
document.write(obj.value); //6
- 构造器调用模式
JavaScript是基于原型继承的语言,对象可以直接从其他对象继承属性。
如果在一个函数前面加上new运算符来进行调用,那么将创建一个隐藏连接到该函数的prototype原型对象的新实例对象。
var F=function(string){
this.status=string;
};
F.prototype.get=function(){
return this.status;
}
var f=new F("hello");
alert(f.get());
- apply调用模式
JavaScript是函数式的面向对象编程语言,函数可以拥有方法。apply()就是函数的一个基本方法,使用这个方法可以调用函数,并修改函数体内的this值。apply方法包括两个参数:第一个参数设置绑定给this的值;第2个参数是包含函数参数的数组。
var array=[5,6,3];
var add=function(){
var i,sum=0;
for(i=0;i<arguments.length;i++){
sum+=arguments[i];
}
//return sum;
alert(sum);
}
var sum=add.apply({},array);
var F=function(string){
this.status=string;
};
F.prototype.get=function(){
//return this.status;
alert(this.status);
};
var obj={
status:'hello'
};
var status=F.prototype.get.apply(obj);
函数的标识符
在函数结构体系中,一般包含这些标识符:函数参数、arguments、局部变量、内部函数、this。
优先级:
this>局部变量>形参>argumments>函数名
例子-在函数结构内显示函数结构的字符串。
function f(){
alert(f);
}
f();
例子-如果在函数f中定义形参f,则同名情况下参数变量的优先级大于函数的优先级。
function f(f){
alert(f);
}
f(true);
例子-比较形参与arguments属性的优先级。
function f(arguments){
alert(typeof arguments);
}
f(true);
function f(arguments){
alert(typeof arguments);
}
f(4);`
function f(arguments){
alert(typeof arguments);
}
var a=[2,3,4];
f(a);
例子-比较arguments属性与函数名的优先级。
function arguments(){
alert(typeof arguments);
}
arguments();
例子-比较局部变量和形参变量的优先级。
function f(x){
var x=55;
alert(x);
}
f(99);
例子如果局部变量没有赋值,则会选择形参变量。
function f(x){
var x;
alert(x);
}
f(99);
例子-局部变量与形参变量混在一起使用
function f(x){
var x=x;
alert(x);
}
f(99);