javascript语言是在运行时前即进行编译的,而this的绑定也是在运行时进行绑定的。也就是说,this实际上是在函数被调用时候发生绑定的,它指向什么完全取决于函数在哪里被调用。

1.默认绑定

例如直接在全局作用域下声明:

var a=2;
console.log(this.a);
  • 在全局作用域下声明的变量或者函数等,都会作为window对象的属性。
  • 这个时候,默认this是绑定到全局作用域下的window对象,如果你去console.log(this);你会发现,你打印出来的是window,尽管你没有声明this就是window,但是js进行了默认绑定。

以至于你运行以下的代码片段:

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

浏览器控制台打印出来的是 2 ;

2.隐式绑定

当函数引用有上下文对象时,在函数调用时,会进行隐式绑定。这么说肯定很抽象,还是举例说明吧。

var a=4;
function foo(){
console.log(this.a);
}
var obj={a:2,foo:foo
}
foo();
obj.foo();

两次会打印出来什么呢?猜一下?

  • foo()会打印出来4,obj.foo()会打印出来2
  • 第一个foo() 使用了默认绑定,this绑定到了全局对象window,打印 this.a 就是打印window.a;
  • 第二个foo()外层的foo函数引用作为obj.foo的属性值,通过obj进行调用,此时的obj就是这个函数引用的上下文对象,this会隐式绑定到obj这个对象上。此时打印的this.a就是obj.a了。

3.显式绑定

在上面两种绑定中,我们都没有去明确地进行强制绑定,而是使用了默认规则的绑定,那么如果我们想要在调用某个函数时特定地改变this的绑定,这个时候就可以用显式绑定了。

还是上代码,然后进行分析。

var a=4;
function foo(){
console.log(this.a);
}
var obj={a:2,foo:foo
}
var foo1=foo.bind(obj);
foo();
foo.call(obj);
foo.apply(obj);
foo.call(window);
foo1();

按照顺序打印出的是 4 ,2 ,2, 4,2

  • 第一次打印了4 使用了默认绑定,foo函数的this绑定到了window。
  • 第二次打印了2 使用了call函数,显式地将foo函数的this绑定到obj对象。
  • 第三次打印了2 apply方法的效果跟call方法一样。
  • 第四次打印了4 call方法显示地将foo函数的this绑定到了obj对象,效果跟默认绑定一样了。
  • 第五次打印了2,bind方法显示地将foo函数的this绑定到了obj,并且返回了一个硬编码后的新函数,赋值给foo1变量进行调用,硬编码就是新函数内部this直接绑定到了指定的对象,也就是obj。

4.new 绑定

使用new方式进行调用函数时,会发生构造函数的调用。怎么解释呢,还是直接上代码加分析。

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

打印出来的是 3 ,2

  • foo函数只是一个普通的函数,直接调用foo(3)只是作为普通函数的调用,会使用默认绑定将this绑定到window上,对window.a也就会全局变量a进行赋值,所以打印出来的是3;
  • foo函数,进行构造调用,this绑定到test对象,故而this.a作为test对象的属性并进行传参赋值。打印出来的test就是{a:2},this.a就是2了。

先上图,然后根据文字阅读

使用new 调用函数之后,该foo函数才作为构造函数进行调用,构造一个全新的对象赋值给test,而test对象的_proto_
指向了test的prototype对象,test的prototype对象有一个属性constructor,指向test的构造函数foo,这个就是javascript的原型链,也是javascript的特性。对于test对象调用的方法以及属性,会先在test对象进行寻找,如果找到的话,就直接进行调用,寻找停止。如果寻找不到,顺着原型链,在test对象的prototype对象寻找,如果找到的话,进行调用,寻找停止,如果还是找不到,会在prototype对象的原型上进行寻找,这个时候_proto_指向了Object的prototype对象,Object的prototype的constructor指向了Object()本身,而一些Obejct的函数如toString等等就是在这个原型上进行调用的,这个时候如果还是找不到需要属性或者方法,那么就是语法错误,未定义了。因为Object的prototype的_proto_指向是null了,也就没有任何对象属性以及方法了。

不是说程序员可以new 很多个对象嘛,但是new出来的对象 原型最终结果却是指向了 空(null),所以还是自己动手丰衣足食吧,哈哈。

一般情况下,使用new函数之后构造的对象,会优先将函数调用到的this绑定到这个对象,如果函数没有返回其它对象,会自动调用返回这个新对象。

总结:

只有对于this绑定的情况有了基本的了解,才能在编写代码时候,避免产生由于绑定带来的未知bug。如果你在调用某个框架插件或者绑定事件的时候,发现this不好用了,有可能是你的this使用绑定错了,打印下console.log(this)在控制台看一看,也许就发现问题了。

如果在阅读中遇到什么问题,欢迎评论以及留言。同时欢迎我的博客陈建光的博客

欢迎评论以及留言,同时欢迎关注我的博客定时不断地更新我的文章 陈建光的博客

浅谈 javascript 中的this绑定问题相关推荐

  1. 浅谈javascript中原型(prototype)、构造函数、对象实例及三者之间的关系

    转自:http://www.cnblogs.com/zhangwei412827/archive/2012/12/14/2816263.html 浅谈javascript中原型(prototype). ...

  2. html 滚动条 scrolltop scrollheight,浅谈JavaScript中scrollTop、scrollHeight、offsetTop、offsetHeight...

    浅谈JavaScript中scrollTop.scrollHeight.offsetTop.offsetHeight 发布时间:2020-07-17 09:27:20 来源:亿速云 阅读:223 作者 ...

  3. 浅谈JavaScript中的NaN

    浅谈JavaScript中的NaN NaN概念以及简单案例 追寻的纯粹该拥有自己的本质.-JC.F 什么是NaN? NaN:NaN(Not a Number),它表示不是数字,但是仍是数值类型. Na ...

  4. 浅谈JavaScript中闭包

    引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...

  5. html dom节点类型,浅谈Javascript中的12种DOM节点类型

    前言 DOM的作用是将网页转为一个javascript对象,从而可以使用javascript对网页进行各种操作(比如增删内容).浏览器会根据DOM模型,将HTML文档解析成一系列的节点,再由这些节点组 ...

  6. 浅谈JavaScript中的事件

    事件在javascript中是响应用户的一种基本操作,本文列举了两种javascript中的事件模型及其绑定的方式,希望能对你的学习带来一点帮助.这些都是非常基础的但或许其中有你所遗漏.(以下事件均针 ...

  7. 浅谈JavaScript中的apply、call和bind

    摘要 三种方法均可改变函数this关键字的指向. apply()接受一参数数组,返回函数执行的结果. call()接受一组参数,返回函数执行的结果. bind()接受一组参数,返回函数体.需在bind ...

  8. 浅谈Javascript中的void操作符

    由于JS表达式偏啰嗦,于是最近便开始采用Coffeescript来减轻负担.举个栗子,当我想取屋子里的第一条dog时,首先要判断house对象是否存在,然后再判断house.dogs是否存在,最后取h ...

  9. 浅谈JavaScript中的对象和类型(上)

    JavaScript是一种不同于任何强类型程序设计语言的脚本语言,这决定了它对于许多强类型语言的程序员来说有很多莫名其妙.难以理解的地方,本文是本人对JavaScript的一些实践总结出来的简单易懂的 ...

最新文章

  1. python yield yield from
  2. UITableView 重用机制
  3. python开发需要掌握哪些知识-学习Python应该掌握哪些知识点?
  4. 一对一交友源码,一对一视频交友源码,这些功能是主流
  5. Linux文件管理以及一些常用的基础命令解析
  6. b+tree数据结构可视化_数据结构: B+Tree及其应用
  7. 获取焦点改变输入框背景色
  8. ES6中object对象属性
  9. flex4自定义皮肤
  10. U盘安装系统时黑屏! 无法进入解决办法
  11. 向mysql中导入数据库文件
  12. python之window下安装python2版的pyv8库 (window install python2 pyv8)
  13. 量化交易之Dual Thrust策略
  14. PDF文件转换成图片的格式
  15. 微信支付委托代扣的服务商模式和直连模式
  16. 安全性、活跃性以及性能问题
  17. web数据可视化(ECharts版)
  18. 哈佛结构和冯诺依曼结构特点
  19. Thunder v7.9.5.4480 Ayu 优化版
  20. 2022 SWPU NSS新生赛|MISC知识点

热门文章

  1. 不上全站https的网站你们就等着被恶心死吧
  2. Web开发常见的软件架构
  3. 单点登录与权限管理本质:session和cookie介绍
  4. 如何在OpenStack环境中实现多Region
  5. 将MongoDB服务加入随机启动
  6. 从游戏脚本语言说起,剖析Mono所搭建的脚本基础
  7. Linux中断处理驱动程序编写【转】
  8. flume-hdfs 按照时间关闭并新开文件
  9. CCNA基础知识汇总
  10. VLAN设置错误,导致部分用户无法上网