浅谈js之this对象

  this对象真的是有时让我们头疼,我们真是分不清它到底指向哪个作用域,它有时的指向真的是不可思议,它本应该这样指向却那样指向。

虽然有这么句话,this是调用执行当前代码的对象的所有者,也就是谁调用它,它就指向谁,那问题来,如果我们分不清谁调用的它,那怎么办呢?

理论部分:

0X00:

js中的圣经红宝书和犀牛书对这部分说的很少,但是很精辟;要真正的深刻理解书上说的,那么你对this就一点也不难,但是像我这种菜鸟怎么可能理解呢???

红宝书

this引用的是函数据以执行的环境对象,this对象是在运行时基于函数执行环境绑定的,在全局中,this等于window,当函数被作为木个对象的方法调用时,this等于那个对象,不过,由于匿名函数的执行环境具有全局性,因此,this对象通常指向window,还有就是每个函数在调用的时候都会自动获取两个特殊变量:this和arguments,放在活动对象中,内部在要使用这两个变量时,只是会在本函数的活动对象中搜索,永远不会沿着作用域链访问外面的活动对象。

犀牛书

this对象没有作用域的限制,嵌套的函数不会从调用它的函数中继承this,如果嵌套函数作为方法调用,其this值指向调用它的对象,如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式)就是undefined(严格模式);很多人误以为调用嵌套函数时this会指向调用外层函数的上下文。

这就是解释的。当你真正理解了this后看这些话,你感觉他们说的this判断就是这么回事很有感觉,但是对于我来说,读过这些话没太有感觉,不理解。

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。

声明以下我说的都是在我们判断this对象指向时可以这么想,其他时候你可别这样想呀!有小部分是不太适合的,那样说的话;

      我说的都是自己的理解,如果你感觉我说的不对,欢迎指正!

      我说的这些例子中有很多是类似的,只是为了让我们加深理解!

0X01:

this往大了说无非就是全局中的和函数(方法)中的,只是这函数(方法)中的太过于复杂;

其实可以大致划分为五类:

  1. 全局下中【this】
  2. 函数中调用【foo(foo2(this))】(这里是指在函数中执行的函数即函数嵌套函数)
  3. 方法调用【obj.foo(this)】(这是是指对象调用函数时)
  4. 构造函数中【new Foo(this)】
  5. apply和call中【foo.apply(obj)】

有时候也不好说是在五种的哪一种;只是大致这样吧;                     参考:http://bonsaiden.github.io/JavaScript-Garden/zh/#function.this

实战部分:

0x00:在全局中的情况

全局中:

0x01:

var a = 1;
console.log(this);//window
console.log(this.a);//1

这就是全局中的this它是指向window对象的,这种情况很简单

0x01:函数调用中的

如果一个函数的调用者是一个函数,那么那个被调用的函数中的this是指向window的

我们就是在对象的方法里调用函数,有时让我们分不清,其实在this眼里,所有的函数都是跟普通函数差不多;

在javascript语言精粹上说,在此模式中this被绑定到全局对象,这是语言设计上的一个错误。

001:setTimeout和setInterval中的this

这个是要单独拿出来的,他们其实都是来自window的方法,这两个函数不管是在哪里调用,;其执行上下文环境是window对象下的环境;

var num = 1;
var obj = {
    num:2,
    show:function() {
        console.log(this.num);
    },
    showNum:function() {
        setTimeout(this.show,1000);
    }
};
obj.showNum();//1

参数中的this是传递引用的过来的,是和showNum中的this是一样的,其实这个this不是重点,在这里,show方法里面的this才是重点

我的理解是当程序执行到setTimeout的时候通过this.show获取对obj对象中show函数引用,show函数里面的this应该指向谁呢?(你不要误认为这个方法定义在obj中就和obj有关系(确实有关系,但是在this对象看来:函数定义在哪里都一样,在它看来你们都是一个个孤立的函数,就看你是在哪里调用的),你就记住这句话:在this对象看来:函数不管定义在哪里,都是一样的,没有区别,不管你是在对象中还是函数中,还是全局中的,都是一样的,我就是看你在哪里调用了,this是和javascript中执行环境有关,而非声明环境有关),

,不要认为show函数是obj的,就和obj有关系,这里就是想当于setTimeout(function(){console.log(this.num)},1000);其实这就是函数中嵌套函数,所以里面的this指向window;如果你感觉setTimeout有特别不和其他函数一样,你就看下面的,一样的,只不过这个是普通函数:

var num = 2;
var obj = {
    num:1,
    foo2:function() {
        function foo3(a) {
            console.log(this);//window
            console.log(a);//1
        }
        foo3(this.num);//this =>obj
    }
}
obj.foo2();

在调用foo3时他参数this就是obj,跟setTimeout中的是一样的;它里面的this也是window,这就是foo3是函数调用的,

 002:

var x = 2;
var obj = {
    x:1,
    a:function () {
        var x = 3;
        var b = function () {
            console.log(this.x);
        };
        b();
    }

}
obj.a();//2

这个和上面那个例子差不多,就是函数中嵌套函数的情况,一定是指向window了

003,简单的:

function foo() {
  function bar() {
    alert(this);
  }
  bar();
}
foo();//window

0x02:方法中的调用

一定指向调用它的那个对象

001

var num = 1;
function foo() {
    console.log(this.num);
}
foo();//1 

这其实就是window对象下的foo()方法的调用 ==》window.foo();只是在全局下可以省去罢了;

002

var obj = {
    num:1,
    foo:function() {
    console.log(this.num);
    }
}
obj.foo();//1

003

var obj1 = {
    num:1,
    showNum1:function() {
        console.log(this.num);
    }
};
var obj2 = {
    num:2,
    showNum2:obj1.showNum1
}
obj2.showNum2();//2

其实obj2等价与这样:

var obj2 = {
num:2,
showNum2:function(){
console.log(this.num);
}
}

只不过这个函数我是引用的obj1中的showNum2函数罢了,这样看你就知道了,再次说明了我说setTimeout时所说的,只不过我们showNum2:obj1.showNum1这样用就给我们一种感觉,它就是跟obj1有关系,其实在this看来没有关系,this就是个有奶便是娘的东西,它不管哪个娘生的它,谁是它亲娘(在哪个地方声明(定义)的它),只要给的奶喝,它就认谁为娘(谁执行调用的它);你一定要抛开声明地方不同,对你的影响;

004

var x= 2;
var obj = {
    x:1,
    fn:function() {
        alert(this.x);
    }
};
// obj.fn();
var test = obj.fn;
test();//2

也是那种情况,

等价与

var test = function(){
    alert(this.x);
}
test();//2

005:

function foo() {
  alert(this.bar);
}

var x = {bar: 10};
var y = {bar: 20};

x.test = foo;
y.test = foo;

x.test(); // 10
y.test(); // 20

006

var x = 10;
var obj = {
    foo:function() {
        alert(this.x);
    },
    x:20
};
with(obj) {
    foo();//20
}

调用foo时就是相当于obj.foo();

007

var x = 3;
var foo = {
    x:2,
    baz:{
        x:1,
        bar:function() {
            return this.x;
        }
    }
}
var go = foo.baz.bar;
console.log(go());//3
console.log(foo.baz.bar());//1

这就是变量go引用了函数function(){return this.x};这个就是foo.baz调用了bar()函数所以this指向调用者foo.baz这个对象

008

function Foo() {}
Foo.prototype.method = function() {console.log(this)};
function Bar() {}
Bar.prototype = Foo.prototype;
var obj = new Bar();
obj.method();//Bar

0x03:构造函数中

function Person() {
    console.log(this);
    this.x = 1;
}
var people = new Person();
console.log(people.x);//10

上面没有显式的创建对象;直接将属性赋值给this对象;没有return语句;

其实在你使用new操作符,调用构造函数其实经历了以下四个过程:

  1. 自动创建一个对象
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
  3. 执行构造函数中的代码
  4. 把这个新对象返回出去(隐式的return)

其实就是这样差不多:

function person() {
    var o = {};
    o.x = 1;
    return o;
}
var people = person();
console.log(people.x);

这个this是有用处的,它可以使每个new实例化的对象都有属于自己的属性,而不全都是从原型中继承而来的。

0x04:apply和call方法中

他们都是在特定作用域中调用函数,实际上等于设置了函数体内的this对象的值,第一个参数在ES3或非严格模式中,传入的的null和undefined都会被全局对象代替,其他的原始值则会被相应的包装对象所代替,在严格模式下,第一个实参是null或undefined时,里面的this就是null或者是undefined,

001

function f() {
    console.log(this.x + " " + this.y);
}
var obj = {
    x:1,
    y:2
}
f.call(obj);//1 2

这里的this就是obj

002

function show() {
    console.log(this);
    function test() {
        console.log(this);
    }
    test();
}
show.call({x:1});//{X:1},window

这里就是首先由于call方法所以改变了作用域,show()函数的this指向了{x:1},test()属于函数调用函数的情况所以是window对象;

上面说的都是javascript语言中this;

现在说说DOM对象中的this

001.

一种是DOM0级事件绑定中的this,

obj.onclick = function () {
console.log(this);//obj
}

上面说了这么多你,你在看这里为什么这个this是obj你知道了吗?因为当你触发事件的时候,是obj对象就会检测它的onclick属性有没有绑定函数,如果绑定了就调用。

002.

DOM2级中的

先来个这样的:

<script type="text/javascript">
var x = 2;
var obj = {
    x:1,
    fn:function(f) {
        f();
    }
}

obj.fn(function(){console.log(this.x);});//2
</script>

它是会显示2的,也就是说这个this是window,和上面我罗嗦了半天的函数调用的情况,函数中调用函数

但是你看这里:

var x = 2;
var test = document.getElementById("test");
test.x = 1;
test.addEventListener(‘click‘,function() {
    console.log(this.x);//1
    console.log(this);//test对象
});

这是怎么回事???要是按照上面的来应该是window对象呀,这就是addEventListener方法的特别之处,它不是不同的函数呀,简单说这个函数的作用就是把第二个参数的的函数,绑定在调用它的那个对象(这里是test)下的,有跟addEventListener的第一个参数的名字相同的属性名下。就类似这样:

test = {
//这里是很多的属性名
//.....
//......
click:function(){
  console.log(this);
}
}

这个函数大体就是这个作用;

而IE的attachEvent就跟上面说的就差不多了,它的this是window;

不写了就写这么多吧。总结就是,this是和执行环境有关,不是和声明函数有关,在你用this的时候要小心点,实在不确定是什么,你就alert一下,不就知道了

下面这些是我的参考,我的很多很多例子就是从他们那里的,要不然那么多情况我怎么一时半会也想不出出来呀,他们写的这些都是精化呀,如果你感觉我写的把你搞晕了的话,还没有明白的话,我建议你看看这些,我相信在你看明白这些后你就对this有自己的理解和认识;

javascript秘密花园:http://bonsaiden.github.io/JavaScript-Garden/zh/#function.this

大叔的:http://www.cnblogs.com/TomXu/archive/2012/01/17/2310479.html

大额_skylar:http://www.cnblogs.com/skylar/p/4042663.html

http://www.cnblogs.com/justany/archive/2012/11/01/the_keyword_this_in_javascript.html

http://www.cnblogs.com/KevinYang/archive/2009/07/14/1522915.html

http://www.cnblogs.com/rush/archive/2012/07/31/2617429.html

javascript高级程序设计

javascript权威指南

时间: 2024-10-08 23:40:16

浅谈js之this对象的相关文章

浅谈js中arguments对象

一.先来看看到底是个啥? arguments对象在JS中应该算数比较特殊的对象.不能显示的创建,只在当前函数调用的时候才可以使用,长得有点像数组,但绝对不是Array的实例. 几点说明: 1.1.arguments实际上是当前函数的一个内置属性,在当前函数内,函数名.arguments等价于arguments,在函数外单独使用arguments是没有意义的; 1.2.arguments对象的长度由实际参数个数决定.1.3.函数中的形参和实参是可以相互影响的. 可以看出,当传入的实参个数少于形参个

浅谈JS之Error对象

[前言] 本文主要介绍下JS的Error name相关属性.   当 JS 引擎执行 JS代码时,会发生各种错误. ①语法错误,通常是程序员造成的编码错误或错别字: ②拼写错误或语言中缺少的功能(可能由于浏览器差异): ③来自服务器或用户的错误输出而导致的错误: ④由于许多其他不可预知的因素: 当发生错误时,JS通常会停止并产生错误消息.技术术语是这样描述的:JavaScript 将抛出异常(抛出错误).JS实际上会创建一个Error对象,该对象带有两个属性name和message. [主体]

浅谈JS的arguments对象

在JavaScript中,arguments属于当前对象的一个内置属性,arguments非常类似于Array对象,但是又不是实例的Array.比如: Array.prototype.testArg = "test"; function funcArg() { alert(funcArg.arguments.testArg); alert(funcArg.arguments[0]); } alert(new Array().testArg); // result: "test

浅谈 js 对象 toJSON 方法

前些天在<浅谈 JSON.stringify 方法>说了他的正确使用姿势,今天来说下 toJSON 方法吧.其实我觉得这货跟 toString 一个道理,他是给 stringify 方法字符串化的时候调用的.看下 MDN 官方文档吧<toJSON behavior>.非常简单,但是要注意的是他和 stringify 方法第二个参数稍微有点不同.因为 stringify 第二个参数是回调函数时,只是对当前 key 对应的值进行修改.而 toJSON 则是对当前对象进行修改.例如: v

浅谈 js 正则之 test 方法

原文:浅谈 js 正则之 test 方法 其实我很少用这个,所以之前一直没注意这个问题,自从落叶那厮写了个变态的测试我才去看了下这东西.先来看个东西吧. ? 1 2 3 4 5 var re = /\d/; console.log( re.test("1") ); console.log( re.test("1") ); console.log( re.test("1") ); console.log( re.test("1"

浅谈 js 语句块与标签

原文:浅谈 js 语句块与标签 语句块是什么?其实就是用 {} 包裹的一些js代码而已,当然语句块不能独立作用域.可以详细参见这里<MDN block> 也许很多人第一印象 {} 不是对象字面量么?怎么成了语句块了?如果在赋值语句或者表达式里用的时候,确实是对象字面量,如: var a = {}; ({toString:function(){return "hehe"}}) + "..."; 是不是很有意思..但是直接使用如: {toString: fu

浅谈JS之AJAX

0x00:什么是Ajax? Ajax是Asynchronous Javascript And Xml 的缩写(异步javascript及xml),Ajax是使用javascript在浏览器后台操作HTTP和web服务器进行数据交换(用户不知道也感觉不出来,就跟桌面应用程序似的进行数据交互),它不会导致页面重新加载,这样才有更好的用户体验. Ajax是基于以下开放标准: javascript(DOM) css html xml(json) 通俗的说就是使用了javascript(DOM)的XMLH

浅解析js中的对象

浅解析js中的对象 说到对象,我首先想到的是每逢过年过节,长辈们老是开玩笑的问我“你找了对象没?”.不说大家都知道,这里的“对象”指的是“女朋友”,但是今天我想要说的js中的“对象”和我们生活中谈到的“对象”不是同一回事,但是其中也有着很多相似之处.    在讲js中的对象之前,我想先抛出几个疑问:    什么是对象?    对象有哪些?    对象能做什么?    如何创建对象?    如何对对象进行操作?    对象有特性么?有的话有哪些特性?    对象有属性么?有的话有哪些?对属性如何操

从window.console&amp;&amp;console.log(123)浅谈JS的且运算逻辑(&amp;&amp;)

从window.console&&console.log(123)浅谈JS的且运算逻辑(&&) 作者:www.cnblogs.com  来源:www.cnblogs.com  发布日期:2015-03-01 一.JS的且运算记得最开始看到window.console&&console.log(123),当时知道能起什么作用但是没有深入研究,最近在研究后总算弄明白了.要理解这个,首先得明白三个知识点第一:短路原则这个大家都非常清楚的了,在做且运算的时候,“同真