浅谈 javascript 中的this绑定问题
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绑定问题相关推荐
- 浅谈javascript中原型(prototype)、构造函数、对象实例及三者之间的关系
转自:http://www.cnblogs.com/zhangwei412827/archive/2012/12/14/2816263.html 浅谈javascript中原型(prototype). ...
- html 滚动条 scrolltop scrollheight,浅谈JavaScript中scrollTop、scrollHeight、offsetTop、offsetHeight...
浅谈JavaScript中scrollTop.scrollHeight.offsetTop.offsetHeight 发布时间:2020-07-17 09:27:20 来源:亿速云 阅读:223 作者 ...
- 浅谈JavaScript中的NaN
浅谈JavaScript中的NaN NaN概念以及简单案例 追寻的纯粹该拥有自己的本质.-JC.F 什么是NaN? NaN:NaN(Not a Number),它表示不是数字,但是仍是数值类型. Na ...
- 浅谈JavaScript中闭包
引言 闭包可以说是JavaScript中最有特色的一个地方,很好的理解闭包是更深层次的学习JavaScript的基础.这篇文章我们就来简单的谈下JavaScript下的闭包. 闭包是什么? 闭包是什么 ...
- html dom节点类型,浅谈Javascript中的12种DOM节点类型
前言 DOM的作用是将网页转为一个javascript对象,从而可以使用javascript对网页进行各种操作(比如增删内容).浏览器会根据DOM模型,将HTML文档解析成一系列的节点,再由这些节点组 ...
- 浅谈JavaScript中的事件
事件在javascript中是响应用户的一种基本操作,本文列举了两种javascript中的事件模型及其绑定的方式,希望能对你的学习带来一点帮助.这些都是非常基础的但或许其中有你所遗漏.(以下事件均针 ...
- 浅谈JavaScript中的apply、call和bind
摘要 三种方法均可改变函数this关键字的指向. apply()接受一参数数组,返回函数执行的结果. call()接受一组参数,返回函数执行的结果. bind()接受一组参数,返回函数体.需在bind ...
- 浅谈Javascript中的void操作符
由于JS表达式偏啰嗦,于是最近便开始采用Coffeescript来减轻负担.举个栗子,当我想取屋子里的第一条dog时,首先要判断house对象是否存在,然后再判断house.dogs是否存在,最后取h ...
- 浅谈JavaScript中的对象和类型(上)
JavaScript是一种不同于任何强类型程序设计语言的脚本语言,这决定了它对于许多强类型语言的程序员来说有很多莫名其妙.难以理解的地方,本文是本人对JavaScript的一些实践总结出来的简单易懂的 ...
最新文章
- python yield yield from
- UITableView 重用机制
- python开发需要掌握哪些知识-学习Python应该掌握哪些知识点?
- 一对一交友源码,一对一视频交友源码,这些功能是主流
- Linux文件管理以及一些常用的基础命令解析
- b+tree数据结构可视化_数据结构: B+Tree及其应用
- 获取焦点改变输入框背景色
- ES6中object对象属性
- flex4自定义皮肤
- U盘安装系统时黑屏! 无法进入解决办法
- 向mysql中导入数据库文件
- python之window下安装python2版的pyv8库 (window install python2 pyv8)
- 量化交易之Dual Thrust策略
- PDF文件转换成图片的格式
- 微信支付委托代扣的服务商模式和直连模式
- 安全性、活跃性以及性能问题
- web数据可视化(ECharts版)
- 哈佛结构和冯诺依曼结构特点
- Thunder v7.9.5.4480 Ayu 优化版
- 2022 SWPU NSS新生赛|MISC知识点