@(javascript)[JavaScript中this的指向]
关于js函数中this的指向的问题
javasript函数中this的指向一直都是许多编程入门新手的一个问题,老师把这个this的指向弄错误。下面我们可以来看看关于this指向的几种情况。
不过在讲之前,请各位始终记住一句话:
JavaScript中的this一直指向触发这个事件(函数)的这个Objoct(对象)。
第一种:函数直接添加在行内
点击看看:
此时的这个alert(this.innerHTML);
事件是直接写在button
这个元素行内的。是这个button
元素触发的这个事件。
第二种:通过对象.事件名来实现
这是html代码
下面是js代码
document.getElementById("box").onclcik = function(){
alert(this.innerHTML);
}
以上的两种方式都很好理解,也不做过多的说明。
第三种:函数的调用的形式
这种方式也是存在许多的变种,先来看看上面例子的一个变种。
这是html代码
下面是js代码
document.getElementById("box1").onclick = a;
function a(){
alert(this);
}
这一种形式的事件与上面的其实是一样的,不过是单独定义了一个函数,然后点击调用这个函数。
在看看下面的例子
下面是js代码
document.getElementById("box1").onclick = function(){
a();
}
function a(){
alert(this);
}
此时的这个与上面的有很相似,不同的就是此时的这个a
函数是在一个事件函数里面执行的。此时的逻辑是:我点击这个ID为box1的button,让后触发事件后面的函数function(){a();}
。此时呢里面的a函数其实还没有执行。到这个函数执行的时候,执行到里面的函数了,a函数自己调用执行(函数加括号执行),那么问题来了,是谁调用的这个a函数呢?答案是:window
。因为不存在上面说的两种以及Object.函数的形式。这个就有点像是定义了一个函数自执行。
像这样
function t(){
console.log(this);
}
/**
* 此时的这个 t 函数是由谁调用的呢(也就是鼠标哪一个对象让他执行的?)
* 答案是的 null
* 而在 js 中,如果 this 的指向是null会自动转换为 window
*/
t();
或者是这样:
function t(){
function t2(){
console.log(this);
}
t2()
}
t();
OK!接下来看看这个:
function intro(){
console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗
分析一下:此时先定义了一个名字是intro
的一个函数,在定义一个dog
对象并赋值name=狗
。下面的代码就是在dog
这个对象上添加一个intro
对象,赋值为一开始定义的那个函数intro
。此时的这个dog
对象就多了一个属性intro
,值是函数。接着在调用这个dog.intro();
。那么是谁调用的呢?很明显是这个dog
对象调用的这个函数。所以此时的这个this
就是指向dog
对象。那this.name
就是狗
了。
OK!再来:
function intro(){
console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗
var cat = {name:"猫"};
cat.intro = dog.intro;
cat.intro(); // 猫
现在多了一个cat
,看这句cat.intro = dog.intro;
。这个是把dog
下面的intro
方法赋值给了cat
下面新建的一个intro
方法。此时涉及到一个内存的问题。js中的对象,函数等都是存放在内存中,给其他对象赋值为这个函数的时候就是让这个对象的这个属性指向内存中的这个函数,所以,不管上面的是怎样赋值,cat
与dog
的intro
的值是指向同一个函数的。不同的是调用他们的对象不同,导致this
不同,所以最后的this.name
的值不同。
再来看看这个呢?
function intro(){
console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗
var cat = {name:"猫"};
cat.intro = dog.intro;
cat.intro(); // 猫
(cat.intro = dog.intro)(); // 空 this 指向window```javascript
function intro(){
console.log('名字是'+ this.name,this );
}
var dog = {name: "狗"};
dog.intro = intro;
dog.intro(); // 狗
var cat = {name:"猫"};
cat.intro = dog.intro;
cat.intro(); // 猫
(cat.intro = dog.intro)(); // 空 this 指向window
此时的在上面的就是多了一句(cat.intro = dog.intro)();
。那为什么就指向window了呢?
上面的这个例子,涉及到的是关于计算机里面的计算,cat.intro = dog.intro 这是一个赋值运算,而赋值运算的结果是 = 右侧的值,此时这个值并不属于任何一个对象,而这个值是一个空,也可以说是一个 null ,所以此是为 null 转为指向 window。可以这么做一个比喻:
一天张三去面馆吃面,给老板说:“老板,一碗牛肉面”,做好面后,此时的这碗牛肉面这个
值
就有了。相当于上面的intro
函数,此时呢他并不属于张三。当老板把这碗面端到张三面前,这是才属于张三。OK。李四也去吃面,进入面馆,看见张三的面。对老板说:“老板,来一碗和他一样的面”。此时老板需要计算,这碗面是什么面?相当于上面的cat.intro = dog.intro
计算。老板计算后才知道这碗面是牛肉面。此时让一个值
加括号执行,那肯定就不行了。此时的这碗面并不属于李四。赋值的结果是是什么呢?当老板把这碗面端到李四面前,这是才属于李四。这就是结果。
需要注意的点就是cat.intro = dog.intro
只是一个赋值过程,值是=
右边的东西。执行cat.intro = dog.intro
会导致一个结果就是cat
下面多了一个intro
属性并且有值。
基本普通的函数中的this存在的问题就是这么多,其他的也就是上面的一些变种。
不过,可以发现,因为this指向window的存在,会导致污染全局,所以多数时候使用构造函数new
的方式更可取,这样this才不会指向全局避免污染全局。
上面说了这么多。其实也就是最开始说的那句:
JavaScript中的this一直指向触发这个事件(函数)的这个Objoct(对象)。