js中使用this

在JavaScript中this 表示当前调用对象,用在函数体内。

this,是函数体内自带的一个对象指针。它始终指向调用对象,当函数被调用时,使用this可以访问调用对象。this关键字的使用范围局限于函数体内或者调用范围内。

如果this没有包含书香,则传递的是当前对象。

this不仅仅局限于对象的方法内,还可以被应用在全局域内,函数内。以及其他特殊上下文环境。

函数的引用和调用

函数的引用和调用分别表示不同的概念,虽然他们都无法改变函数的定义作用域,但是引用函数能够改变函数的执行作用域,而调用函数时不会改变函数的执行作用域的

var o = {
    name:"对象o",
    f:function(){
        return this
    }
}

o.o1 = {
    name:"对象o1",
    me:o.f            //引用对象o的方法f
}

在上面的例子中,函数中的this所代表的是当前执行域对象o1.

var who = o.o1.me()

alert(who.name)       //返回的是对象o1

如果把对象o1的me属性值改为函数调用

var o = {
    name:"对象o",
    f:function(){
        return this
    }
}

o.o1 = {
    name:"对象o1",
    me:o.f()            //调用对象o的方法f
}

则函数中的this表示的是定义函数时所在的作用域对象o;

var who = o.o1.me()

alert(who.name)       //返回的是对象o

使用call()和apply()可以直接改变被执行函数的作用域,使其作用域指向传递的参数对象,因此函数中包含的this关键字也指向参数对象

function f(){
    if(this.constructor ==arguments.callee) alert("this=实例对象")
    else if(this == window) alert("this=window对象")
    else alert("this=其他对象")
     
}

f();  //指向window
new f(); //指向实例对象
f.call(1); //指向的其他对象

在下面例子中call()方法把函数f()强制转换为对象o的一个方法并执行,这样函数f()中的this就指代对象o,所以this.x=1 this.y=2

function f(){
    alert(this.x + this.y)
}

var o = {
    x:1,
    y:2
}

f.call(o)

闭包体在哪被调用,则其中包含的this就会指向哪儿。

为了避免因继承关系而影响父类中this所代表的对象,我们可以为父类定义私有函数,然后再把它的引用传递给其他付给成员,

异步调用之事件处理函数

<body>
	<input type="button" value="Button">
</body>
<script type="text/javascript">
	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;

</script>

这里的方法 f() 所包含的this不再指向对象o,而是指向按钮button,因为他是被传递给按钮事件处理函数之后,再被调用执行的,函数的执行作用于发生了变化,所以不再指向定义方法时所指向的对象。

this的安全策略

确保在同一域中操作包含this的方法或函数,应避免把包含有this的全局函数或方法动态用在局部作用域的对象中,也应该避免在不同作用域的对象之间互相引用包含this的方法或者属性。

例子

<body>
	<input type="button" value="按钮1" onclick = "f()">
	<input type="button" value="按钮2" onclick = "f()">
	<input type="button" value="按钮3" onclick = "f()">
</body>
<script type="text/javascript">
	
	 function f(){
		alert(this.value)
	}
</script>

这中写法是错误的,因为this在这里始终指向winows对象,而不是用户期待的按钮对象

但是我们换一种思维,把this作为参数进行传递,那么他就会代表当前对象

<body>
	<input type="button" value="按钮1" onclick = "f(this)">
	<input type="button" value="按钮2" onclick = "f(this)">
	<input type="button" value="按钮3" onclick = "f(this)">
</body>
<script type="text/javascript">
	
	 function f(o){
		alert(ovalue)
	}
</script>

设计静态的指针

如果要确保构造函数的方法在初始化之后,方法所包含的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)

这样,this始终指向的是原型对象,而不再是子类的实例对象

同时我们可以使用call()或者apply()方法强制指定this的指定对象。

应用this

function f(){
    this.x = function(x){
        return x
    }
}

f();

alert(f.x(4))        //使用函数f名调用方法x(),则返回编译错误

方法x()实在函数f体内定义的,由于函数f是被window对象调用的。所以thisz执行的是window

当使用new运算符调用函数,则this指向的是实例对象,

function f(){
    this.x = function(x){
        return x
    }
}
//使用new运算符实例化函数f,并把实例化对象赋值给了a,则a就有了函数f的结构
var a  = new f();

alert(a.x(4))        //使用函数f名调用方法x(),则返回编译错误

在全局作用域中,所有变量和函数的调用对象都是window,.

函数的调用模式

在js中有四种函数调用模式 方法调用模式,函数调用模式,构造器调用模式,和apply调用模式

方法调用模式

当一个函数被保存为对象的一个属性的时候,称之为一个方法,当一个方法被调用的时候,this被绑定到当前调用对象。

函数调用模式

当一个函数不是一个对象的属性时,它将被当作一个函数来调用

当函数用此模式调用时,this被绑定到全局变量,这是语言设计上的一个缺陷,如果语言设计正确,当内部函数被调用时,this应该仍然绑定到外部函数的this变量,这个设计错误的后果是方法不能利用内部函数来帮助工作,解决方法:如果该方法定义一个变量并将它赋值为this,那么内部函数就可以通过这个变量访问this,按照约定,将这个变量命名为that

构造器调用模式

js是基于原型继承的语言,对象可以直接从其他对象继承属性,当今大多数语言都是基于类的语言,虽然原型继承有着强大的表现力,但它偏离了主流的用法,并不被广泛理解,如果在一个函数前面加上new运算符来进行调用,那么将创建一个隐藏连接到该函数的prototype原型对象的新实例对象,同时this将会被绑定到这个新实例对象上。

var F = new function(string){
    this.status = string;
}

F.prototype.get = function(){
    return this.status;
}
var f = new F("new Object")
document.writeln(f.get())  // "new Object"

apply调用方法

就一句话 apply可以调用函数并修改this的指向

比如f.apply(g, [])  那么 在f中的this就i指向了g.

函数的标识符

以下标识符在函数体内的优先级是 左侧大于右侧

this>局部变量>形参>arguments>函数名

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Guess you like

Origin blog.csdn.net/Chen_leilei/article/details/112429823