以下函数利用classaname遍历标签属性的时候,企图触发事件,将本函数的调用者以this的状态传递给下一个函数,但是在调用的时候,this更改了指向,最后打印出来的结果是,this指向window;最后不得已,将move(this),改为move(x[i])才打印正常;
window.οnlοad=function(){
var x=document.getElementsByClassName("div");
for(var i=0;i<x.length;i++){
x[i].οnclick=move(this);
}}
function move(member){
console.log(member);
} ; // window
于是就this进行探索,以下是对this指向的总结,希望有所收获:
1,this 的指向在函数定义的时候不能够确定,它指向的永远是最后调用它的那位;
function a(){
var name="bob";
console.log(this.name);
}
a(); // undefined; 最后是在window执行环境中调用,在window中并没有找到name;
2,如果一个函数中有this,这个函数中有多个对象包裹着this,尽管this是被最外层对象调用的,this仍然指向离自己最近的那个对象。
var o={
a:{
b:{
m:10,
fn:function(){
console.log(this);
}; } } }
window.o.a.b.fn(); // m:10,fn:f
打印结果也就是对象b,this并没有指向window,而是指向b.
3,当this遇到return时:
如果return的值是一个对象,那么this就指向那个return过来的对象,
function a(){
this.age=10;
return {} 或者 return function(){}
}
var m=new a();
m.age; //undefined;
反之,如果return的不是对象,那么this还是指向函数实例,其中null虽然是对象,但是this还是指向函数实例;
function a(){
this.age=10;
return 1 或者 return undefined;
}
var m=new a();
m.age; // 10;
4,每个函数在创建的时候都会产生一个this和一个arguments;而且这个函数的内部函数还不能够直接访问到这个函数的this,但是如果把外部函数中的this用一个变量保存起来,内部的函数(比如闭包)虽然不能直接访问this,但是却可以访问外部函数的变量;
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name;
}; } };
alert(object.getNameFunc()()); //"My Object"
5,全局作用域或者普通函数中this指向全局对象window
//直接打印
console.log(this) //window
//function声明函数
function bar () {console.log(this)}
bar() //window
//function声明函数赋给变量
var bar = function () {console.log(this)}
bar() //window
//自执行函数
(function () {console.log(this)})(); //window
6,方法调用中谁调用this指向谁
//对象方法调用
var person = {
run: function () {console.log(this)}
}
person.run() // person
//事件绑定
var btn = document.querySelector("button")
btn.onclick = function () {
console.log(this) // btn
}
//事件监听
var btn = document.querySelector("button")
btn.addEventListener('click', function () {
console.log(this) //btn
})
//jquery的ajax
$.ajax({
self: this,
type:"get",
url: url,
async:true,
success: function (res) {
console.log(this) // this指向传入$.ajxa()中的对象
console.log(self) // window
}
});
//这里说明以下,将代码简写为$.ajax(obj) ,this指向obj,在obj中this指向window,因为在在success方法中,独享obj调用自己,所以this指向obj
7,在构造函数或者构造函数原型对象中this指向构造函数的实例
//不使用new指向window
function Person (name) {
console.log(this) // window
this.name = name;
}
Person('inwe')
//使用new
function Person (name) {
this.name = name
console.log(this) //people
self = this
}
var people = new Person('iwen')
console.log(self === people) //true
//这里new改变了this指向,将this由window指向Person的实例对象people
8,this的指向可以强制改变:
利用 bind(),apply(),call();
callback(); ----->callback.bind( object1 );
可以使得callback()函数中的this强制指向对象object1;
9,对于函数内部的this,谁调用它,它就指向谁;若没有明确的调用对象,即使一个函数定义在另一个函数内部,this仍然指向window;
function fire(){
function wall(){
console.log(this);}
wall();
}
fire(); // window;
第二个例子:
var obj={
name:"bob",
fire:function(){
function wall(){
console.log(this);
}
wall(); //没有明确的对象调用它,仅仅是独立的函数在执行;
} }
obj.fire(); //window;
凡是作为独立函数调用,无论它的位置在哪里,它的行为表现,都和直接在全局环境中调用无异{
10,一个函数被一个对象包含的时候,它的this隐式绑定到这个对象上:
var obj={
a: 1,
fire:function(){
console.log(this.a);
}
obj.fire(); //1
和这个函数效果相同:
function fire(){
console.log(this.a);
}
var obj={
a: 1,
fire:fire
}
obj.fire(); // 1
fire函数并不会因为它被定义在obj对象的内部和外部而有任何区别,也就是说在上述隐式绑定的两种形式下,fire通过this还是可以访问到obj内的a属性,这告诉我们:
1. this是动态绑定的,或者说是在代码运行期绑定而不是在书写期
2. 函数于对象的独立性, this的传递丢失问题
11,this隐式绑定丢失与寻回:
var a=2;
var o={
a: 1,
fire:function(){
console.log(this.a);
}
}
function ani(fn){
fn();}
ani(obj.fire); // 2
本来隐式绑定this应该指向obj,但是由于隐式绑定丢失,所以this指向的是window;
那么什么情况下this会丢失隐式绑定呢?只有一种情况:当包含this的函数没有执行,而是被当作值传递,或者被当作回调函数的参数的情况下,会丢失。利用call()函数将丢失的this找回来:
var a=1;
var obj={
a: 2,
fire: function(){
console.log(this.a);
}}
var wall=obj.fire; //此处函数被当作值传递,丢失this
wall.call(obj); // 2 call()函数使wall的this指向obj
另外,在《javascript高级程序设计》中,提到一段程序,就是因为函数未直接执行,而是被当作参数传递而丢失this:
var handler = {
message: "Event handled",
handleClick: function(event){
alert(this.message); } };
var btn = document.getElementById("my-btn");
EventUtil.addHandler(btn, "click", handler.handleClick); //警告框弹出:undefined
因为handler.handleClick未执行函数,仅仅当作参数被调用,那么我们执行它就可以避免this丢失:
EventUtil.addHandler(btn, "click", function(event){
handler.handleClick(event) } ); // 打印结果是Event handled;