JavaScript this 的理解

来源:互联网 发布:加内特2004季后赛数据 编辑:程序博客网 时间:2024/05/17 06:21

this 对象是在运行时基于函数的执行环境绑定的:在全局函数中,this 等于 window,而当函数被视为某个对象的方法时,this 等于这个对象。不过匿名函数的执行环境具有全局性,因此其 this 对象通常指向 window

(function() {     console.log(this === window); // true })();

每个函数在被调用的时候都会自动取得两个特殊的变量,this 和 argument ,内容函数在搜索这两个变量时,只会搜索到其活动对象为止,因此永远无法访问外部函数中的这两个变量。

this 的指向总体可以分为四种情况:
1. 直接调用
2. 作为函数对象方法调用
3. 构造函数调用
4. call 跟 apply 方法调用

  1. js 中 this 在函数定义的时候是确定不了的,只有在函数运行的时候才能确定。
  2. 如果一个函数中有 this,但是它没有被上一级的对象所调用,那么 this 指向的就是 ==window==
  3. 如果一个函数中有 this,这个函数被上一级的对象所调用,那么 this 指向的就是==上一级的对象==
  4. 如果一个函数中有 this,这个函数中包含多个对象,尽管这个函数是被最外层的对象所调用的,this 指向的也只是它的上一级的对象。
  5. 如果返回值是一个对象,那么 this 指向的就是那个返回的对象,如果返回值不是一个对象,那么 this 还是指向函数的实例。
  6. javascript 中 function 也是对象,window 是全局变量

this 的指向是不可以改变的,如下:

var obj = {     name: "xiaoming" } function getName() {     this = obj;     console.log(this.name); } getName(); // 运行报错
var name = "global"; var obj = {     name: "local",     getName: function() {         return function() { // 该匿名函数为闭包            return this.name; // 返回的是?         };     } }; console.log(obj.getName());

这个答案当然是 “global” 。因为我们知道每个函数在调用的时候会获取两个对象:this和arguments。而内部函数在搜索这个两个对象时只会搜索到其活动对象为止。而匿名函数的执行环境具有全局性,所以这个this就指向了全局window。

如果需要访问匿名函数外部变量

var name = "global"; var obj = {     name: "local",     getName: function() {         var that = this;         return function() {             return that.name; // local         };     } }; console.log(obj.getName());

不可以改变 this 的值,但可以把 this 用变量存储起来,这样 this 的指向就不会变了

js 中的 call 方法

function hello(con){    alert(this + " " + con);}hello.call("hello","world");//弹出 hello world

call() 的用法
1. 把第二个到最后一个参数当作函数执行时传入的参数
2. 把函数执行时的 this 指向第一个参数
3. 执行函数

js 执行函数的时候会默认执行以上的操作,即执行函数操作 func() 相当于 fun.call(window,p1,...);
ES5 中有三种函数调用形式:

func(p1,p2...)obj.child.method(p1,p2)func.call(context,p1,p2);

如果传的 context 是 null 或 undefined ,那么 window 对象就是默认的 context (严格模式下默认 context 是 undefined)。

第三种,才是正常的调用形式。
例如:

func(p1,p2); 等价于 func.call(undefined,p1,p2)obj.child.method(p1,p2) 等价于 obj.child.method.call(obj.child,p1,p2)

[] 语法:

function fn (){ console.log(this) }var arr = [fn, fn2]arr[0]() //这里面的 this 又是什么呢?

我们可以把 arr0 想象成 arr.0() ,虽然后者有语法错误,但是形式与转换代码里的 obj.child.method(p1,p2) 对应上了,于是就可以转换了

arr[0]() 假象为 arr.0() 然后转换为 arr.0.call(arr)那么里面的 this 就是 arr 了

总结
1. this 就是 call 一个函数时,传进去的 context
2. 如果你的函数调用形式不是 call 形式,则可转换为 call 形式。

实例一:

function a(){    var user = "gray";    alert(this.user);   //undefined    alert(this);        //window}a();

a() 相当于 window.a(), 或 a.call(undefined),window 中并没有定义 user,因此是 undefined

实例二:

var a= {    user:"gray",    fn:function(){        alert(this.user);    }};a.fn();     //gray

相当于 window.a.fn() 或a.fn.call(a),这里用到了第三条规则,fn 被上一级对象 a 调用,因此 this 指向的对象 a。

实例三:

var a= {    user:"gray",    fn:function(){        alert(this.user);    }};var b = a.fn;b();    //undefined

this 永远指向的是最后调用它的对象,也就是看它执行的时候是谁调用过的。此处 b 只是指向 a.fn,并没有执行该函数,而 this 是在执行时才能确定指向的,因此,真正执行的 b() 相当于 window.b() ,或者 b.call() 所以 this 指向 window。

==实例 四:==

针对第四条规则,查看以下例子

var o = {    a:10,    b:{        // a:12,        fn:function(){            console.log(this.a); //undefined        }    }}o.b.fn();

尽管对象 b 中没有 a 属性,这个 this 指向的也是对象 b,因为 this 只会指向它的上一级对象,不管这个对象中有没有 this 所要访问的属性。此例中,b 中虽然可以读到 a 的值,但是 b 没有 a 属性,所以 this.a 为 undefined

构造函数 this

 function Fn(){    this.user = "GC";}var a = new Fn();console.log(a.user); //GC

new 操作符做四件事:

1. 创建一个新的对象2. 将构造函数的作用域赋给了新的对象(因此 this 指向了该对象)3. 执行构造函数的代码(为这个新对象添加属性)4. 返回新对象。

这里之所以对象 a 可以点出函数 Fn 里面的 user ,是因为 ==new 关键字可以改变 this 的指向==,将这个 this 指向对象 a,这里是说 a 是对象,因为用了 new 关键字就是创建了一个对象实例,这里用变量 a 创建了一个 Fn 的实例(相当于复制了一份 Fn 到对象 a 里面),此时仅仅只是创建,没有执行,而调用这个函数的是对象 a,那么为什么对象 a 中会有 user ,因为已经复制了一份 Fn 函数到对象 a 中,用了 new 关键字就等同于复制了一份。

为什么 this 会指向 a ?首先 new 关键字会创建一个空对象,然后会自动调用一个 apply 方法,将 this 指向这个空对象,这样的话,函数内部的 this 就会被这个空的对象替代。

## 当函数有返回值

实例一:

function fun(){    this.user = "gray";    return 1;}var f = new fun();alert(f.user);      //gray

实例二:

 function fun(){    this.user = "gray";    return {};}var f = new fun();alert(f.user);      //undefined

实例三:

function fn()  {      this.user = 'gray';      return function(){};}var a = new fn;  console.log(a.user); //undefined

实例四:

function fn()  {      this.user = 'gray';      return undefined;}var a = new fn;  console.log(a.user); //gray

还有一点,虽然 null 也是对象,但这里 this 还是指向那个函数的实例

实例五:

function fn()  {      this.user = 'gray';      return null;}var a = new fn;  console.log(a.user); //gray

比较上述几个例子,如果返回值是一个对象,那么 this 指向的就是那个返回的对象,如果返回值不是一个对象,那么 this 还是指向函数的实例。

注意
1. 在严格模式下,默认的 this 不是 window ,而是 undefined

0 0