`
zccst
  • 浏览: 3292347 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

js-this作用域

阅读更多
作者:zccst

2014-12
具体日子记不清了,反正是那段时间彻底弄清楚了this作用域指向。
前面的文字都没错,常见的就是那四种。还需要继续探讨的是:
1,当做函数调用,无论在什么时候都是window
比如:
i = 0;
var o = {
    i: 1,
    fn1: function(){
        this.i = 10;
        function m1(){
            alert(this.i);
            this.i = 100;
        }
        m1();
    },
    fn2: function(){
        
    },
}
o.fn1();

各路大神,大家说说alert(this.i);是什么?
答案是0.
理由就是我刚才说的看如何调用的,虽然m1方法隐藏在fn1中,貌似this指向o,其实不是。

2,setTimeout中匿名函数的作用域是什么?
答:window,无论在什么时候。



2014-5-7
this作用域以前专门学习研究过,但发现依然不够全面和完整。现在继续学习
先列出之前看过的结论:
函数在被调用的时候会意外接受两个参数:this和argument,其中this的值跟取决于函数的调用模式
1,方法调用模式 o.a() //this指的o
2,函数调用模式 a() //this指的windows
3,构造器调用模式 new a() //this为a的实例对象
4,apply(call)的间接调用模式 a.apply(xx,[yy]) //this指的xx

但是,上面的描述并没有指出背后的联系,换一种描述方式:
在这里列出this在ECMAScript中的不同含义:

(1) 在全局执行环境中使用this,表示Global对象,在浏览器中就是window对象。

(2) 当在函数执行环境中使用this时,情况就有些复杂了。如果函数没有明显的作为非window对象的属性,而只是定义了函数,不管这个函数是不是定义在另一个函数中,这个函数中的this仍然表示window对象。如果函数显示地作为一个非window对象的属性,那么函数中的this就代表这个对象。(当然可以使用apply或者call函数来取代默认this的引用,详见[P88])

(3) 当通过new运算符来调用函数时,函数被当做一个构造函数,this指向构造函数创建出来的对象。
参考:
《JavaScript基础与案例开发详解》清华大学出版社



定义一个函数,在不同的作用域中调用时this指代不同

当this使用在函数代码中事情就变得有趣多了。这种情况是最难的也会引发很多的问题。在函数代码中,this值的第一(可能也是最重要的)特性就是不能 静态的绑定到一个函数上。正如上面已经提到的,this值在进入上下文时就已经被决定了,在函数代码的情形下,每次this值可以是完全不一样的。

然而,在代码运行时,this值是不可改变的。例如,不能给this赋一个新值,因为this不是变量(相反,python编程语言中,可以显式的定义self对象,在运行的时候self对象可重复改变)
var foo={x:10};
var bar={
    x:20,
    test:function(){
        console.log(this===bar);//true
        console.log(this.x);//20
        //this=foo;//error,不能改变this值
    }
};
//当进入上下文时,this值由"bar"对象决定的。为什么这样-将在下面详细讨论
bar.test();//true,20
foo.test=bar.test;
//然而,此时在这里的this将指向"foo"-即使我们调用同一个函数
foo.test();//false,10


(当我们在一些关于javascript 的文章和书本中会看到“this值由函数如何定义来决定:如果是全局函数,this值被设置为全局对象,如果函数时一个对象的方法,this值设置为这个 对象”-这是一个错误的描述)。从下面我们可以看出即使是一般的全局函数,也能够被产生不同this值的调用表达式所触发。
function foo(){
    console.log(this);
}
foo();//打印this为Window
console.log(foo===foo.prototype.constructor);//true
//但是对于同一函数的另一种调用表达式形式,this值是不同的
foo.prototype.constructor();//打印this为foo
调用一个被定义为对象方法的函数,但是this值不会被设置为这个对象也是同样可能的:

var foo={
    bar:function(){
        console.log(this);
        console.log(this===foo);
    }
};
foo.bar();//foo,true
var exampleFunc=foo.bar;
console.log(exampleFunc===foo.bar);//true
//同一函数的另一种调用表达式形式,得到不同的this值
exampleFunc();//global,false






2013-09-10
最近看到一句话说,js中的对象其实就是一些hash映射。简单说就是名值对,只不过这些名字对同用一个上下文(context)this。
var obj = {
    fun1 : function(){
    },
    fun2 : function(){
        //在使用fun1时,像使用自己的变量一样
        var local = this.fun1();//如果有参数,还可以传递参数
    },
    fun3 : function(){
    },
};







2013-8-27
this关键字

每一个方法或函数都会有一个this对象,this对象是方法(或函数)在执行时的那个环境,也可以说是这个函数在那个作用域下运行的。
说的更通俗一点:this就相当于咱们平时说话时候说的“我”,“我家”的概念。就是说当一个方法在运行的时候,它是属于谁的。它在运行的时候它的家是谁家。
this的概念比较抽象,是讲课的时候的难点也是重点。
关于this的具体表示那个对象,和函数的运行方式(或调用方式)有关。

在JavaScript中一共有四种调用模式:
方法调用模式(对象属性模式)、
函数调用模式(就是普通的函数执行)、
构造调用模式(应该叫实例上的方法模式更好)
和apply调用模式。


一、当它为一个对象上的方法的时候,this是当前这个对象
方法调用模式(或称:对象属性模式)
先了解一个概念:方法和函数的区别。方法和函数本质一样,形式不同而已。看下例:
function fn(){
    alert(this)
}

这样就是定义了一个函数,当:fn()的时候,叫这个函数运行。同样是上面这个fn函数,如果把它赋值给一个对象的属性,就成了方法了,看下面的例子。
var obj=new Object();//先定义一个对象obj
obj.objFn=fn;

那现在的obj.objFn就是方法了,但其实objFn和fn指向的是同一个内存地址。但fn是直接定义的,就是函数,而objFn是obj这个对象上的一个属性,则objFn就是方法了。方法和函数本质上是一样的,只是在不同的情况下的叫法不同。
但当fn运行的时候,弹出的是window(任何函数被调用,this都表示window);而objFn运行的时候,弹出的是object,因为当它做为一个方法运行的时候,this关键字表示的是objFn这个属性所属的这个对象obj。也就是说,在这种情况下,this表示obj。
再啰嗦一遍:当函数成为一个对象的属性的值的时候,这个函数里的this指向当前这个对象(这时候函数就变成了方法)
    再啰嗦第三遍:当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。方法可以使用this去访问对象,所以它能从对象中取值或修改对象。this到对象的绑定发生在调用的时候。这个“超级”迟绑定使得函数可以对this高度复用。通过this可取得它们所属对象的上下文的方法称为公共方法。


二、函数调用模式
当函数并非一个对象的属性时,那么它被当做一个函数来调用。此模式下this绑定到全局对象。通过在对象内将this赋值给that,可以使函数模式下调用that来访问指定对象。
(就是上面解释的函数方式)


三、类的实例上的方法中的this指向当前的实例
例如:
function Person(){
 
}
Person.prototype.cry=function (){alert(this)}
var rose=new Person();
rose.cry();//现在这个cry就被称做方法,这个方法里的this就表示rose这个实例。

详细的讲解,请见《面向对象和设计模式》的课堂讲解和视频


四、使用call和apply方法强制改变this关键字
(附在面向对象一章的讲解里)
测试题:
题目一:
var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
        return this.name;
     };
    }
};
alert(object.getNameFunc()()); //The Window

解析:object.getNameFunc后面跟了两对括号。先运行object.getNameFunc(),这个方法运行后返回了一个函数,就是这个方法里面定义的那个匿名函数,然后再让这个匿名函数运行。
可以分解成以下步骤:
var fn= object.getNameFunc();//object.getNameFunc这个方法里的this是表示object这个对象,但它返回的是一个函数,返回的这个函数里的这个this则表示window了
fn();//当返回的这个函数运行的时候,this表示是window这个对象


和上一题目类似的题:
function a(){
alert(this);
}
var arr = [1,2,3];
arr.f = a;
arr.f();//会输出什么

解析:把a函数赋给arr的属性f,则f就成为arr这个对象上的方法了,它运行的时候就表示arr这个数组对象。
如果直接这样:a();  则这时候的this表示的是window这个对象
分享到:
评论

相关推荐

    js代码-017 018--作用域,变量提升,以及优先级,预解析,this的指向

    js代码-017 018--作用域,变量提升,以及优先级,预解析,this的指向

    深化理解Javascript中this的作用域_.docx

    深化理解Javascript中this的作用域_.docx

    深入理解Javascript中this的作用域

    对大多数有OOP开发经验的开发人员来说this是当前作用域中引用普通元素的标识符,但是在Javascript中它却显得古灵精怪的,因为它不是固定不变的,而是随着它的执行环境的改变而改变。在Javascript中this总是指向调用...

    深入理解js函数的作用域与this指向

    函数的作用域与this指向是js中很重要的一部分,理清这点东西需要个逻辑,看看我的逻辑怎么样… 下面是个提纲,可以直接挑你感兴趣的条目阅读。 • 函数的定义方式:直接定义(window下,内部定义),对象的方法,...

    深入理解js函数的作用域与this指向.docx

    深入理解js函数的作用域与this指向.docx

    javascript中的this作用域详解

    Javascript中this的指向一直是困扰我很久的问题,在使用中出错的机率也非常大。在面向对象语言中,它代表了当前对象的一个引用,而在js中却经常让我觉得混乱,它不是固定不变的,而是随着它的执行环境的改变而改变。...

    深入理解javascript作用域第二篇之词法作用域和动态作用域

    本文是深入理解javascript作用域系列第二篇——词法作用域和动态作用域 词法作用域  第一篇介绍过,编译器的第一个工作阶段叫作分词,就是把由字符组成的字符串分解成词法单元。这个概念是理解词法作用域的基础  ...

    Js作用域和this关键字1

    1 function varscope(){所谓作用域链就是:一个函数体中嵌套了多层函数体,并在不同的函数体中定义了同一变量, 当其中一个函数访问这个变量时,便

    javascript 中 this 的用法.docx

    在全局作用域中使用 this 会返回全局对象,在浏览器环境下是 window 对象, 在 Node.js 环境下是 global 对象。例如: console.log(this === window); true function test() { console.log(this === window); } ...

    wjp2018#vuecss#06-对象、作用域和this1

    向对象中添加属性/添加方法首先创建一个对象:向对象中添加属性:对象的属性值可以是任何的数据类型,也可以是个函数:obj.sayName = function

    Javascript中的作用域和上下文深入理解

    主要介绍了Javascript中的作用域和上下文深入理解,本文讲解了作用域 VS 上下文、变量作用域、“this”上下文、执行上下文(Execution Context)、作用域链等内容,需要的朋友可以参考下

    javascript 嵌套的函数(作用域链)

    嵌套的函数(作用域链) 当你进行函数的嵌套时,要注意实际上作用域链是发生变化的,这点可能看起来不太直观。你可把下面的代码置入firebug监视值的变化。 代码如下: var testvar = ‘window属性’; var o1 = {test...

    JS this作用域以及GET传输值过长的问题解决方法

    在开发项目的时候,前端遇到两个比较隐蔽的问题。 问题一.专IE7浏览器,IE URL参数过长问题,引发HTTP Status 122...解决方法: 把原项目采用jsonp get的数据方法改为 常规post数据方法 问题二. this作用域问题 原因:t

    通过JS运行机制的角度说说作用域

    有过一定编程经验的同学,一定不会对作用域感到陌生,在C/C++/Java中等语言中,作用域从来没有JavaScript中的作用域那样令人困惑以致于成为一个大多数JS开发者都难以跨过的门槛。 作用域形成机制 JS中存在的三种...

    JavaScript作用域链实例详解

    对于JavaScript而言,理解作用域更加重要,因为在JavaScript中,作用域可以用来确定this的值,并且JavaScript有闭包,闭包是可以访问外部环境的作用域的。 每一个JavaScript的函数都是Function对象的一个实例,...

    you Don't Know JS-前三卷(中文)

    you Don't Know JS-前三卷入门与进阶、作用域与闭包、this与对象原型对

Global site tag (gtag.js) - Google Analytics