关于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 ...
随机推荐
- 【转】批量删除redis中的key
1. DEL 直接加键名称 DEL key1 key2 key3 127.0.0.1:6379> DEL site_msg_99973 false site_msg_99974 fals ...
- 多行文字在一个div中上下左右居中
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- mysql linux 区分大小写
查看大小写区分 mysql> show variables like "%case%"; +------------------------+-------+ | Varia ...
- uC/OS-III 概要
本章主要对 uC/OS-III 实时操作系统做一些概要介绍,使读者对 uC/OS-III 有个整体的浅 认识,为后面的章节的详细讲解做一个铺垫. 下图是 uC/OS-III 系统从底层到上层的文件结构 ...
- dp之分组背包hdu3033 最少取1次的解法(推荐)
题意:有n双鞋子,m块钱,k个品牌,(一个品牌可以有多种价值不同的鞋子),接下来n种不同的鞋子,a为所属品牌,b为要花费的钱,c为所能得到的价值.每种价值的鞋子只会买一双,有个人有个伟大的梦想,每个品 ...
- tomcat架构分析(valve源码导读)
出处:http://gearever.iteye.com 源码面前,了无秘密 ----侯捷 在tomcat架构分析(valve机制)(http ...
- 【精】C# 中的委托和事件(转)
C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真 ...
- ngApp指令,也就是ng-app属性
翻译:https://docs.angularjs.org/api/ng/directive/ngApp 使用这个指令去 自动引导 一个AngularJS 应用程序. ngApp 指令规定了html ...
- 在shell 中字符串,文件,数字的比较
hadoop fs -test -e /path/exist ] ;then echo 'exist' else echo 'Error! path is not exist' fi 在shell中如 ...
- 修改 login的串口重定向
1 在console-telnet 使用vi工具编辑 /etc/inittab 文件 vi /etc/inittab (回车)2 按 i 进入编辑模式:3 将文件中的ttyS0 改为 ttyS3 ...