关于JavaScript中的this
1.关于this的误会。
误会(1):this指向所在函数本身。
我们常常会对this产生各种误会,比如说我们可能认为this会指向所在函数本身,但实际上并非如此。
function foo (){
this.count ++;
}
foo.count = 0;
for(var i=0;i<5;i++){
foo();
}
console.log(foo.count);
上面的例子旨在使用函数的this指向this,通过foo函数的count属性计算foo被调用的次数。根据这个目的,输出应该是5,因为for循环了五次,foo函数被调用了5次。但实际上呢?
我们新建一个js文件,命名为test.js,代码如下:
实际输出如下:
输出的foo.count值为0。看上去foo中的this并没有指向foo,那么this指向了哪里呢?
通过chrome JavaScript调试器可以发现,this指向了window全局作用域,并没有如我们预期的指向foo本身。
误会(二):this指向函数所在作用域
通过上面的例子,可能你很快就能得出结论:this指向所在函数所在的作用域。比如上一个例子中,函数foo位于全局作用域(在宿主环境中就是window),foo中的this便指向了全局作用域,但是果真如此吗?
function foo (){
var count = 0;
function bar (){
this.count ++;
}
for(var i=0;i<5;i++){
bar();
}
return count;
}
上面的代码,旨在foo内部,声明一个bar函数用于控制foo作用域内的count变量,实现计算bar被调用次数的功能。理论上,bar函数中的this应该会指向bar所在的作用域,所以this也可以调用count(和bar函数同作用域),应该输出为5。但实际输出呢?
实际输出仍然为0!说明this根本没有指向bar所在的作用域,那么this指向哪了呢?
实际上,this还是指向了window作用域,真是非常神奇。
要想了解this的工作方式,我们先了解一下this的绑定方式。
2.this的绑定规则
(1)默认绑定
当函数独立调用时,这条规则就是无法应用其他规则时的默认规则。
直接使用不带任何修饰的函数,this会指向全局环境。
function foo (){
this.count = 100;
}
foo(); //直接使用,函数未经修饰
console.log(window.count); //输出全局环境中的count变量,就是函数中的this.count,结果为100
但是this不总是指向全局环境,当使用严格模式时,this会被禁止指向全局环境。
function foo (){
"use strict"; //使用严格模式
this.count = 100;
}
foo();
console.log(window.count); //输出:Uncaught TypeError: Cannot set property 'count' of undefined
(2)隐式绑定:
function foo (){
console.log(this.count);
}
var obj = {
count:100,
foo:foo
};
obj.foo(); //输出100
当所调用的函数是某个对象的成员函数时,函数中的this会指向函数所在的对象。
隐式绑定可能会存在绑定丢失的场景,当函数作为参数传入到另外一个函数时,作为参数的函数所绑定的this会失效。
function foo(){
console.log(this.count);
}
function bar (func){
func();
}
var count = 0;
var obj = {
count : 100,
foo : foo
};
bar(obj.foo); //会输出0
如上例,当obj.foo作为参数传入到函数bar时,原来绑定的this指向obj被修改为指向全局变量window。所以使用回调函数,可能会修改传入参数函数的this指向。
(3)显式绑定
使用call()或者apply()函数可以显式强制的绑定函数的this。
function foo (){
console.log(this.count);
}
var count = 'window!';
var obj1 = {
count : 100,
foo : foo
};
var obj2 = {
count : 200,
foo : foo
};
foo.call(obj1); //输出100
foo.call(obj2); //输出200
如上例所示,call两次修改了foo的this指向。使其指向某个固定的对象。当call的传入的第一个参数为null时,所修改函数的this指向不会被显式修改。
(4)new 绑定
使用new操作符,可以将函数的this指向新创建的对象。
function Foo(name, age){
this.name = name;
this.age = age;
}
var obj = new Foo('Tom',99);
console.log(obj);
输出如下:
新构建的obj对象具有了一系列属性,都是用函数Foo中的this所实现。
通过这个原理,我们可以简单的实现一个_new_函数,以实现new操作符的功能。
function _new_ (func , arr){
var obj = {};
func.apply(obj,arr);
return obj;
}
function Foo (name, age){
this.name = name;
this.age = age;
}
var obj = _new_(Foo,['Jerry',99]);
console.log(obj);
输出的obj如下:
说明基本的传参构造对象功能已经实现了。
3.四种绑定规则的优先级
new绑定 > 显示绑定 >隐式绑定 > 默认绑定
判断this绑定的顺序:
1.判断是否是new调用,是的话就是new绑定,函数中的this会指向新构造的对象。
2.判断是否是显示绑定,即是否是通过函数原型中的apply方法或者call方法调用 (还要注意bind返回的函数,this指向也会被修改)。
3.判断是否是隐式绑定,及通过某个对象调用。是的话,this会指向所属对象。
4.如果都没有的话,就是默认绑定,this指向全局对象window;严格模式下指向undefined。
……更过this相关,有待补充,如有错误,欢迎指正!
关于JavaScript中的this的更多相关文章
- javascript中的Array对象 —— 数组的合并、转换、迭代、排序、堆栈
Array 是javascript中经常用到的数据类型.javascript 的数组其他语言中数组的最大的区别是其每个数组项都可以保存任何类型的数据.本文主要讨论javascript中数组的声明.转换 ...
- javascript中的this与函数讲解
前言 javascript中没有块级作用域(es6以前),javascript中作用域分为函数作用域和全局作用域.并且,大家可以认为全局作用域其实就是Window函数的函数作用域,我们编写的js代码, ...
- JavaScript 中的数据类型
Javascript中的数据类型有以下几种情况: 基本类型:string,number,boolean 特殊类型:undefined,null 引用类型:Object,Function,Date,Ar ...
- javascript中的操作符详解1
好久没有写点什么了,根据博主的技术,仍然写一点javascript新手入门文章,接下来我们一起来探讨javascript的操作符. 一.前言 javascript中有许多操作符,但是许多初学者并不理解 ...
- 掌握javascript中的最基础数据结构-----数组
这是一篇<数据结构与算法javascript描述>的读书笔记.主要梳理了关于数组的知识.部分内容及源码来自原作. 书中第一章介绍了如何配置javascript运行环境:javascript ...
- javascript中变量提升的理解
网上找了两个经典的例子 var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); // 10 var ...
- 前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型
前端开发:面向对象与javascript中的面向对象实现(二)构造函数与原型 前言(题外话): 有人说拖延症是一个绝症,哎呀治不好了.先不说这是一个每个人都多多少少会有的,也不管它究竟对生活有多么大的 ...
- 简单分析JavaScript中的面向对象
初学JavaScript的时候有人会认为JavaScript不是一门面向对象的语言,因为JS是没有类的概念的,但是这并不代表JavaScript没有对象的存在,而且JavaScript也提供了其它的方 ...
- Javascript中的valueOf与toString
基本上,javascript中所有数据类型都拥有valueOf和toString这两个方法,null除外.它们俩解决javascript值运算与显示的问题,本文将详细介绍,有需要的朋友可以参考下. t ...
- 关于javascript中的this关键字
this是非常强大的一个关键字,但是如果你不了解它,可能很难正确的使用它. 下面我解释一下如果在事件处理中使用this. 首先我们讨论一下下面这个函数中的this关联到什么. function doS ...
随机推荐
- 每日英语:China Overtakes U.S. in Number of Diabetes Cases
China is now home to the world's largest diabetes population. The number of people who have diabetes ...
- 歌手右侧快速入口ABCD....
1.通过v-for将右侧内容渲染出来,并绝对定位到右侧 2.给每个li绑定touchStart事件,并绑定自定义属性data-index=index: 3.点击每个li,通过e来获取所绑定的自定义属性 ...
- mproxy: c 语言实现的一个最小的http代理,支持FQ
https://github.com/examplecode/mproxy mproxy 使用说明 这是一个微型的http代理服务器实现,使用c语言实现,核心代码量不足500行,不依赖任何第三方的库( ...
- win10无法使用内置管理员账户打开应用
win10无法使用内置管理员账户打开应用怎么办 听语音 | 浏览:42181 | 更新:2016-02-21 10:04 | 标签:WIN10 1 2 3 4 5 6 7 分步阅读 推荐视频 mo ...
- java中volatile关键字的含义<转>
在java线程并发处理中,有一个关键字volatile的使用目前存在很大的混淆,以为使用这个关键字,在进行多线程并发处理的时候就可以万事大吉. Java语言是支持多线程的,为了解决线程并发的问题,在语 ...
- 网页图表Highcharts实践教程标之加入题副标题版权信息
网页图表Highcharts实践教程标之加入题副标题版权信息 Highcharts辅助元素 辅助元素图表的非必要元素.如标题.版权信息.标签.加载动态.它们不和图表数据发生关联,仅仅是额外说明一些基 ...
- Entity Framework应用:管理并发
理解并发 并发管理解决的是允许多个实体同时更新,实际上这意味着允许多个用户同时在相同的数据上执行多个数据库操作.并发是在一个数据库上管理多个操作的一种方式,同时遵守了数据库操作的ACID属性(原子性. ...
- Entity Framework开发介绍
一.Entity Framework概要 Entity Framework是微软的Object Relational Mapper(对象关系映射),也就是我们平常说的ORM,它可以让应用程序开发者将关 ...
- java list分组 list里面分装的都是对象 按照对象的属性来分组
http://www.iteye.com/problems/86110 —————————————————————————————————————————————————————————— List& ...
- DataTables 固定列时实现 hover
之前说过 DataTables 表格固定栏使用方法 .分析下它的代码,如下图 它实现固定左侧的原理就是把需要固定的数据复制一份,覆盖在全部数据的上面,用绝对定位固定在左边. 这样子有个问题就是,表格的 ...