对JavaScript中this指针的新理解分享

一直以来对this的理解只在可以用,会用,却没有去深究其本质。这次,借着《JavaScript The Good Parts》,作了一次深刻的理解。(所有调试都可以在控制台中看到,浏览器F12键)

下面我们一起来看看这个this吧。

在我们声明一个函数时,每个函数除了有定义时的parameters(形参),自身还会有额外的两个参数,一个是this,一个是arguments(实参)。arguments就是函数实际接受到的参数,是一个类数组。arguments我只做个简略的介绍,重点我们放在this指针上。

在面向对象变成中,this十分重要,它的值取决于调用的模式。而在JavaScript中,一共有4中调用模式:方法调用模式、函数调用模式、构造函数调用模式、apply调用模式。

方法调用模式

当一个函数是作为一个对象的属性时,我们通常称这个函数是这个对象的一个方法。当这个方法被调用时,this就会指向该方法所属对象。

代码如下:

<script type="text/javascript">
    var people = {
        name : "Yika",
        sayName : function(){
            console.log(this.name);   //"Yika"
                        //this已经绑定在了people对象上了
        }
    }
    people.sayName();
</script>

如栗子所示,this指向了sayName对象,这种通过this取得所属对象上下文的方法,就是公共方法。(publice method)

函数调用模式

当一个函数被调用时并非某个对象上的方法,那么它就是作为一个函数被调用的。

这种模式调用,this会指向window对象,即使这个函数或许是在外部函数里调用的,我们来看栗子。

代码如下:

<script type="text/javascript">
    var name = "window-Yika";
    var people = {
        name : "people-Yika",
        student : function(){
            console.log(this);   //这里的this绑定的是对象people
            function sayName(){
                var name = "sayName-Yika";
                console.log(this.name); //window-Yika
          //即使sayName函数本身和它所在的people对象都有name值,但是this是指向window的
            };
            sayName();
        }
    }

people.student();
</script>

这样一看,是不是大概知道该怎么解决JavaScript这个“设计错误"了呢。

是的只要在student函数里面,也就是第6行,将this缓存起来。然后再将this通过变量转移到sayName函数里就可以解决啦!

代码如下:

var people = {
        name : "people-Yika",
        student : function(){
            var self = this; //将this缓存起来
            function sayName(){
                var name = "sayName-Yika";
                console.log(self.name);  //"people-Yika",此时的self指向的是people对象
            };
            sayName();
        }
    }

构造函数调用模式

  JavaScript里一讲到构造函数,脑海里就会有:“函数名大写!调用的时候要用new操作符!” 函数名大写好理解,是为了规范统一构造函数的命名。可是你有没有深究过为什么要用new呢?如果在一个函数前面带上new来调用,那么函数后台会创建一个指向该函数prototype的新对象,同时this也绑定在新对象上。JavaScript是一门基于原型继承的语言,对原型prototype不是很清楚的同学可以自己去查一下资料,我重点放在this上面。

我们先来看看构造函数一般长什么样子。

代码如下:

<script type="text/javascript">
    function People(name){
        this.name = name;    //这里的this,用new调用后便指向了新对象Yika    
     this.sayName = function(){
          console.log(this.name);  //输出
      }
    }
  var Yika = new People("Yika"); 
   Yika.sayName();  //输出“Yika" ,因为Yika是通过new调用得来的,this都绑定在了Yika对象上。
</script>

乍一看,好像不是好懂,怎么刚才在函数里的this是指向window,现在不用缓存就可以指向People函数呢?

没关系,刚才不是说函数通过new调用,会在背地里自己做“做坏事”么,我们一起看看到底做了哪些事。

代码如下:

<script type="text/javascript">
    function People(name){
        var that = {};   //坏事一:自己生成一个对象
        that.name = name;
        that.sayName = function(){
            console.log(that.name);
        };
        return that;    //坏事二,自己会改变return的行为,return刚生成的对象
    }
    var Yika = People("Yika"); //这里可以省略new,模仿调用new操作符
    Yika.sayName(); //和刚才一样输出"Yika"
</script>

这样看就明白清楚了吧,new不仅会生成一个对象,而且还会自动return这个对象,这样自然this便指向了这个新对象。

千万记得要用 new 去调用构造函数,不然出了问题,是没有警告的,所有大写约定还是十分有必要的。

Apply调用模式

apply方法让我们构建一个参数数组传递给调用函数,也允许我们改变this值。

function.apply(this绑定的值, arguments参数数组)

apply可以说的东西太多了,我这里只举个的栗子来帮助大家理解:

代码如下:

<script type="text/javascript">
    function People(name){
        this.name = name;
        this.sayName = function(){
            console.log(this.name);   //sayName这个方法是属于People构造函数的
        }
    }
    function Student(name){
        People.apply(this, arguments);//借用构造函数的集成方式,就是在Student构造函数里,通过apply调用People构造函数,并改变People的this值
                                      //这样每次创建Student实例时,都会调用People构造函数
    }
    var student = new Student("Yika");
    student.sayName(); //输出“Yika”
</script>

我们可以通过apply轻易的修改函数的this绑定对象,和apply相似的方法call也有一样的效果,有兴趣的同学可以自己搜索学习一下。

好了,总算讲完改变this的四种调用模式了,方法调用模式和构造函数调用模式会用的更多,也会更重要一点,而函数调用模式,我们则要学会避开其中的陷阱。

若有错误,请及时反映,我会尽快纠正,以防误导他人,谢谢!

(0)

相关推荐

  • 小议Javascript中的this指针

    (1) 在全局执行环境中使用this,标识Global对象,在浏览器中就是window对象. (2)当在函数执行环境中使用this时,如果函数没有明显的作为非window对象的属性,而是只是定义了函数,不管这个函数是不是定义在另一个函数中,这个函数中的this仍然标识window对象.如果函数显示地作为一个非window对象的属性,那么函数中的this就代表这个对象. 复制代码 代码如下: var o=new Object; o.func=function() { alert((this===o

  • 老生常谈Javascript中的原型和this指针

    1.Javascript中的原型: 原型prototype是Javascript中特有的一个概念.通过原型,Javascript可以实现继承机制. Javascript本身是基于原型的,每一个对象都有一个prototype属性.而Object对象的prototype属性为null. 下面来看一个使用原型实现继承的例子: 1.1使用原型实现继承: function Person(name){ this.name = name; this.getName = function(){ return t

  • Javascript this指针

    前言 Javascript是一门基于对象的动态语言,也就是说,所有东西都是对象,一个很典型的例子就是函数也被视为普通的对象.Javascript 可以通过一定的设计模式来实现面向对象的编程,其中this "指针"就是实现面向对象的一个很重要的特性.但是this也是Javascript中一个非常容易理解错,进而用错的特性.特别是对于接触静态语言比较久了的同志来说更是如此. 示例说明 我们先来看一个最简单的示例: <script type="text/javascript&

  • 浅谈JavaScript中的this指针和引用知识

    this是javascript的一个关键字,随着函数使用场合不同,this的值会发生变化.但是总有一个原则,那就是this指的是调用函数的那个对象. this指针在传统OO语言中,是在类中声明的,表示对象本身.在JavaScript中,this表示当前上下文,即调用者的引用 ********this永远指向的是(函数对象)的所有者 this和全局对象: var a = 1; function foo(){ var b = 2; console.log(this.a+b);//3 } foo();

  • 你必须知道的Javascript知识点之"this指针"的应用

    很多人都知道this指针,这篇文章的主要目的是为了培训我们公司的新人.默认的this指针指向规则1this指针默认指向方法调用时为其指定的对象,如:obj.fun(),fun方法体中的this指针指向obj. 复制代码 代码如下: var user = { name: '段光伟' };user.getName = function(){ return this.name; };user.getName();  //返回'段光伟' 复制代码 代码如下: var user = { name: '段光

  • 探寻JavaScript中this指针指向

    探寻JavaScript中this指针指向 首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题. 为什么要学习this?如果你学过函数式编程,面向对象编程,那你肯定知

  • 对JavaScript中this指针的新理解分享

    一直以来对this的理解只在可以用,会用,却没有去深究其本质.这次,借着<JavaScript The Good Parts>,作了一次深刻的理解.(所有调试都可以在控制台中看到,浏览器F12键) 下面我们一起来看看这个this吧. 在我们声明一个函数时,每个函数除了有定义时的parameters(形参),自身还会有额外的两个参数,一个是this,一个是arguments(实参).arguments就是函数实际接受到的参数,是一个类数组.arguments我只做个简略的介绍,重点我们放在thi

  • JavaScript中Require调用js的实例分享

    在我最初开始写 JavaScript 函数时,通常是这样的: function fun1() { // some code here } function fun2() { // some other code here } ... 函数全写在全局环境中,项目很小时,通常不会有什么冲突问题. 但代码多了后,渐渐就发现,函数名称(英文词汇)有点不够用了.于是引入命名空间的概念,开始模块化代码. 命名空间下的函数 在命名空间下,我的代码这样写: var com = com || {}; com.zf

  • javascript中的原型链深入理解

    要弄清楚原型链就要先弄清楚 function 类型,在javascript中没有类的概念,都是函数,所以它是一门函数式的编程语言.类有一个很重要的特性,就是它可以根据它的构造函数来创建以它为模板的对象.在javascript中,函数就有2个功能 第一. 作为一般函数调用 第二. 作为它原型对象的构造函数 也就new() 我们来看一个例子 复制代码 代码如下: function a(){ this.name = 'a'; } 当创建一个函数,它会发生什么呢? 第一.它会创建1个函数对象 也就是a

  • JavaScript中的函数重载深入理解

    在JavaScript中有一种特殊的数据类型---Function类型,JavaScript的每个函数都是Function类型的实例.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定. <pre name="code" class="html">function sum(num1,num2) { return num1 +num2; } alert(sum(10,10)); //20 var other = sum; ale

  • Javascript中异步等待的深入理解

    在本文中,我们将探讨async/await对于每个Javascript开发人员来说,异步编程的首选工具.如果您不熟悉javascript,请不要担心,本文将帮助您async/await从头开始理解. 介绍 async/await 是javascript中的一种模式,可使您的代码以同步方式执行,但又不影响javascript的异步行为. 定义异步功能 要定义一个异步函数,您所要做的只是在函数定义之前添加一个async关键字. // async function always returns a p

  • javascript中自定义对象的属性方法分享

    首先介绍下关联数组: 复制代码 代码如下: <script> var test=new Object(); test["a"]=1; test["b"]="string"; test["c"]=false; alert(test["a"]); </script> 执行上面的代码,显示1.在javascript中,方法和属性一样当做值来看待. 复制代码 代码如下: <script

  • 关于javascript中this关键字(翻译+自我理解)

    下文有大概70%的内容出自http://www.quirksmode.org/js/this.html,另外30%是我自己对它的理解和感想.希望能对有需要的人一点帮助... 首先,先看一个很典型的关于this关键字题目: 复制代码 代码如下: var name = 'hong' var obj = { name: 'ru', getName: function(){ return function(){ return this.name; }; } } alert(obj.getName()()

  • 针对JavaScript中this指向的简单理解

    首先必须要说的是,this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象(这句话有些问题,后面会解释为什么会有问题,虽然网上大部分的文章都是这样说的,虽然在很多情况下那样去理解不会出什么问题,但是实际上那样理解是不准确的,所以在你理解this的时候会有种琢磨不透的感觉),那么接下来我会深入的探讨这个问题. 为什么要学习this?如果你学过函数式编程,面向对象编程,那你肯定知道干什么用的,如果你没有学过,那么暂时可以不

  • JavaScript中Array的实用操作技巧分享

    一.关于Array Array的创建很灵活,可以使用Array构造函数,也可以直接创建数组"字面量". var arr = new Array(); //[] var brr = Array(); //[] 两者等效 var arr = Array(3); //[] arr.length; //3 长度为3的空数组 var arr = Array(22,33,'qq',{}); //[22, 33, "qq", Object] var brr = [22,33,'q

随机推荐