深入理解this

你可能听过很多this,就像C#中的this就是指向一个他的实例对象,

      但是在javascript中,我可能要告诉你,他是在运行时动态绑定的

他指向什么,完全取决于函数在哪里调用

        在这里还要说明一个东西,调用栈----------->通俗的来讲,就是为了到达一个方法所调用的所有方法

    我们可以用浏览器自带的调试工具来查看

        function foo(){
            console.log(this.a);
        }
        var b={
            a:10,
            foo:foo
        };
        b.foo();//10

    从运行的结果,我们就可以看出来,当调用b.foo()时this被绑定到了b   

了解了调用栈以后,我们在来了解一个词,调用位置

  调用位置,顾名思意,也就是我调用这个函数的上一个位置,也叫做调用位置0-0

        function foo(){
            console.log(this.a);
        }
        var a=20;
        foo();//20

仔细的人就会发现,上面的调用位置和下面的调用位置都是全局,那么是什么让他们产生了差异?

如果你仔细的看的话,就会发现他们的差别就在于调用foo()的方法不同,上面的是b.foo(),而下面的只是foo();

  也就是这一点的差异,让绑定发生的变化

为了说明这点我们需要指明绑定时的4个规则

1.默认绑定

        function foo(){
            console.log(this.a);
        }
        var a=20;
        foo();//20

独立函数调用。可以把这条规则看作是无法应用其他规则时的默认规则。

  在这里需要说明的是,只有在非严模式下,默认绑定才会绑定到全局,否则会报ReferencesError错误

2.隐式绑定

另一条需要考虑的规则是调用位置是否有上下文对象,或者说是否被某个对象拥有或者包含,不过这种说法可能会造成一些误导。

我们就拿上面的那个例子来说

        function foo(){
            console.log(this.a);
        }
        var b={
            a:10,
            foo:foo
        };
        a=20;
        b.foo();//10
        foo();//20

在这个例子中,我们通过b.foo();来调用foo()函数,在这里需要注意的是b.foo只是对foo()函数的一个引用

那么你可能就会说既然只是一个引用,那么我调用它和直接调用它没有什么区别吧,但是,我们还记得第一个标题?

  this是在被调用时被绑定的!!!  而我们调用的地方正是b,所有this就指向了b!!!!!!!!!!!!

当然使用这种隐式绑定也有一定的缺点 !!!           请看下面的例子

        function foo(){
            console.log(this.a);
        }
        var b={
            a:10,
            foo:foo
        };
        a=20;
        var bar=b.foo;
        bar();//20 这里是20你想通了吗?
        

一种更微妙、更常见并且更出乎意料的情况发生在传入回调函数时

        function foo(){
            console.log(this.a);
        }
        var b={
            a:10,
            foo:foo
        };
        a=20;
        function bind(fn){
            fn();
        }
        bind(b.foo);//20 在这里输出的是20 是因为b.foo 仅仅就是一个函数的引用,所以他调用了默认绑定,指向this

上面的例子和下面的结果一样

        function foo(){
            console.log(this.a);
        }
        var b={
            a:10,
            foo:foo
        };
        a=20;
        setTimeout(b.foo,1000);//20  可以看到结果和上面一样!!!!!!!!

3.显示绑定

  Call(this,参数)

        var b1={
            a:10,
            foo:function foo(){
                console.log(this.a);
            }
        };
        var b2={a:20};

        b1.foo.call(b2);//20 在这里我们显示的让this指向了b2这个对象

  Apply(this,参数数组)

        var b1={
            a:10,
            foo:function foo(t,e){
                console.log(this.a+t+e);
            }
        };
        var b2={a:20};

        b1.foo.apply(b2,[1,2]);//23  我们可以看到,他们除了在参数的传递上不同外,其他的都一样

bind

        function foo(){
            console.log(this.a);
        }
        var a=200;
        var b={a:100};
        setTimeout(foo.bind(b)//100
        ,1000);

当然在这里有必要说一下bind的语法 function.bind(Object),也就是将一个对象绑定到一个函数上

4.New绑定

使用 new 来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。
  1. 创建(或者说构造)一个全新的对象。
  2. 这个新对象会被执行 [[ 原型 ]] 连接。
  3. 这个新对象会绑定到函数调用的 this 。
  4. 如果函数没有返回其他对象,那么 new 表达式中的函数调用会自动返回这个新对象

function foo(a) {
this.a = a;
}
var bar = new foo(2);
console.log( bar.a ); // 2

那么有这4个绑定规则,哪个的优先权更高呢?---------------------->请看下章

时间: 2024-10-23 13:16:34

深入理解this的相关文章

Python——深入理解urllib、urllib2及requests(requests不建议使用?)

深入理解urllib.urllib2及requests            python Python 是一种面向对象.解释型计算机程序设计语言,由Guido van Rossum于1989年底发明,第一个公开发行版发行于1991年,Python 源代码同样遵循 GPL(GNU General Public License)协议[1] .Python语法简洁而清晰,具有丰富和强大的类库. urllib and urllib2 区别 urllib和urllib2模块都做与请求URL相关的操作,但

关于SVM数学细节逻辑的个人理解(三) :SMO算法理解

第三部分:SMO算法的个人理解 接下来的这部分我觉得是最难理解的?而且计算也是最难得,就是SMO算法. SMO算法就是帮助我们求解: s.t.   这个优化问题的. 虽然这个优化问题只剩下了α这一个变量,但是别忘了α是一个向量,有m个αi等着我们去优化,所以还是很麻烦,所以大神提出了SMO算法来解决这个优化问题. 关于SMO最好的资料还是论文<Sequential Minimal Optimization A Fast Algorithm for Training Support Vector

2.2 logistic回归损失函数(非常重要,深入理解)

上一节当中,为了能够训练logistic回归模型的参数w和b,需要定义一个成本函数 使用logistic回归训练的成本函数 为了让模型通过学习来调整参数,要给出一个含有m和训练样本的训练集 很自然的,希望通过训练集找到参数w和b,来得到自己得输出 对训练集当中的值进行预测,将他写成y^(I)我们希望他会接近于训练集当中的y^(i)的数值 现在来看一下损失函数或者叫做误差函数 他们可以用来衡量算法的运行情况 可以定义损失函数为y^和y的差,或者他们差的平方的一半,结果表明你可能这样做,但是实际当中

理解信息管理系统

1.信息与数据的区别是什么? 数据是记录客观事物,可鉴别的符号,而信息是具有关联性和目的性的结构化,组织化的数据.数据经过处理仍是数据,而信息经过加工可以形成知识.处理数据是为了便于更好的解释,只有经过解释,数据才有意义,才可以成为信息.可以说信息是经过加工以后,对客观世界产生影响的数据. 2.信息与知识的区别是什么? 信息是具有关联性和目的性的结构化,组织化的数据,知识是对信息的进一步加工和应用,是对事物内在规律和原理的认识.信息经过加工可以形成知识. 3.举一个同一主题不同级别的数据.信息.

深度理解div+css布局嵌套盒子

1. 网页布局概述 网页布局的概念是把即将出现在网页中的所有元素进行定位,而CSS网页排版技术有别于传统的网页排版方法,它将页面首先在整体上使用<div>标记进行分块,然后对每个快进行CSS定位以及设置显示效果,最后在每个块中添加相应的内容.利用CSS排版方法更容易地控制页面每个元素的效果,更新也更容易,甚至页面的拓扑结构也可以通过修改相应的CSS属性来重新定位.  2. 盒子模型 盒子模型是CSS控制页面元素的一个重要概念,只有掌握了盒子模型,才能让CSS很好地控制页面上每一个元素,达到我们

深入理解Java:类加载机制及反射

一.Java类加载机制 1.概述 Class文件由类装载器装载后,在JVM中将形成一份描述Class结构的元信息对象,通过该元信息对象可以获知Class的结构信息:如构造函数,属性和方法等,Java允许用户借由这个Class相关的元信息对象间接调用Class对象的功能. 虚拟机把描述类的数据从class文件加载到内存,并对数据进行校验,转换解析和初始化,最终形成可以被虚拟机直接使用的Java类型,这就是虚拟机的类加载机制. 2.工作机制 类装载器就是寻找类的字节码文件,并构造出类在JVM内部表示

八幅漫画理解使用 JSON Web Token 设计单点登录系统

原文出处: John Wu 上次在<JSON Web Token – 在Web应用间安全地传递信息>中我提到了JSON Web Token可以用来设计单点登录系统.我尝试用八幅漫画先让大家理解如何设计正常的用户认证系统,然后再延伸到单点登录系统. 如果还没有阅读<JSON Web Token – 在Web应用间安全地传递信息>,我强烈建议你花十分钟阅读它,理解JWT的生成过程和原理. 用户认证八步走 所谓用户认证(Authentication),就是让用户登录,并且在接下来的一段时

谈谈你对Hibernate的理解

答: 1. 面向对象设计的软件内部运行过程可以理解成就是在不断创建各种新对象.建立对象之间的关系,调用对象的方法来改变各个对象的状态和对象消亡的过程,不管程序运行的过程和操作怎么样,本质上都是要得到一个结果,程序上一个时刻和下一个时刻的运行结果的差异就表现在内存中的对象状态发生了变化. 2.为了在关机和内存空间不够的状况下,保持程序的运行状态,需要将内存中的对象状态保存到持久化设备和从持久化设备中恢复出对象的状态,通常都是保存到关系数据库来保存大量对象信息.从Java程序的运行功能上来讲,保存对

IOS contentOffset该如何理解

contentOffset是哪个点??? 首先从字面理解:内容偏移 我可是查了词典的!!! 对于contentOffset有的时候我们会产生错误理解. 我不想在这里介绍错误的理解避免不必要的混淆. 我们什么时候会遇到contentOffset??? 更多的时候是在滚动试图中,我们可以通过它结合代理实现一些方法. 比如轮播(我会在下一篇介绍轮播的实现原理至于代码如果需要我可整理出来) 那么请让我通过图片演示来解释contentOffset. (一) 图一中绿色为屏幕也就是最大的显示范围也是滚动视图

如何理解“字符串是一组由16位组成的不可变的有序序列”

疑惑点: 1.16位 2.不可变 3.有序序列 解惑: 1.16位指的是:字符串每个字符所占用的空间为16bits 比特(2 bytes);这是因为JS采用的是unicode编码,每个字符需要2个字符. 2.不可变指的是: 字符串对象一旦创建出来,便不能被更改.这可能有些难理解,但事实确实如此.你可能会认为s+='1' 只是在 s 后面增加一个元素 1 而已,但事实是: 先将 s 拷贝一份,记为 temp 在 temp 末尾加上'1' 将 s 变量指向 temp,并删去原来的s 这一特性,可以从