最近在看 你不知道的javascript 这本书,在第二部分看到了一个比较重要的知识点 那就是 this对象的全面认识,于是做一下笔记

博主本人在看这本书之前也一直以为 this 是指一切引用类型的本身 但直到最近才明确了 this 对象的见解 关于this 对象误解书上也作了一些解释 下面我来整理一下

先看下面的例子:

 function foo(num){
console.log(num);
this.count++;
} foo.count = 0;for (var i = 0; i < 10; i++) {
if (i > 5) {
foo(i);
}
}
console.log("函数被调用了多少次?" + foo.count); //0

在js 里面 函数即对象 我们将foo 函数定义了a 属性,在循环调用 foo函数中 foo函数的a 属性自增1

但是为什么最后输出结果为0 ???

这就是我们对this 对象的第一个误解:this指向函数自身

实际上this.a 指向了 window对象,不相信??看看下面代码的变化吧

 function foo(num){
console.log(num);
this.count++;
} foo.count = 0;
window.count = 0; window.count 还没有被初始化
for (var i = 0; i < 10; i++) {
if (i > 5) {
foo(i);
}
}
console.log("函数被调用了多少次?" + foo.count); // console.log("count 属性变成了 window属性了!!但window属性并没有初始化:" + window.count); //NaN

打开你的编译器试试便知晓~

函数的执行 this.count 并没有指向 foo函数的本身而是当 foo函数循环执行的时候为 window对象 添加 count属性 并且每次循环为这个属性自增1

但是因为 window对象中 并没有count 这个属性所以输出的只是 NaN 的结果

那么我们可以把window.count属性初始化一下

function foo(num){
console.log(num);
this.count++;
} foo.count = 0;
window.count = 0; for (var i = 0; i < 10; i++) {
if (i > 5) {
foo(i);
}
} console.log("函数被调用了多少次?" + foo.count); // console.log("count 属性变成了 window属性了!!而且window属性得到了初始化:" + window.count);//调用次数为

初始化之后我们就可以看到函数的正确调用次数结果了~

我们再看看第二个误区:

我们对this 对象的第二个误解:this对象指向函数的作用域

看看下面例子:

 window.a = "i'm window";

     function fun(){
var a = "this is fun";
this.bar();
} function bar(){
console.log(this.a);
} fun();// i'm window
bar.call(window);//上面的行为等价于这个

解释一下:

作者在书上的原意是 想把bar 的执行引用绑定在fun 函数中
但是因为 fun是在 window对象下执行的 所以this对象 指向的是 window对象
所以 this.bar() 变成了在window对象下执行函数 bar(),或直接等于在 window 对象下直接调用了 bar() 这个函数
此行为也等价于 bar.call(window)

当然要让bar 函数在fun 函数里面调用何必要花那么大的功夫

直接将bar()函数写在 fun中就可以了

另外声明一点就是:this 对象不指向函数的词法作用域(详情请看 你不知道的javascript 闭包和作用域的一章)

小结:

那么this 的对象指的是哪一个呢?

看了上面的两个例子,我们不难发现this 对象大多数都和 window对象有关系 那是为什么呢?

再举个例子:

function fun(){
this.a = "i'm function fun";
console.log(this.a);
} fun();//i'm function fun console.log(window.a);//i'm function fun

表面上看 在fun函数内部定义了 this.a 这一条语句就是给fun 函数添加了一个a 属性

但是当fun 函数执行的时候 实际上却将a 这个属性赋值给了 window对象
因此在下一句里面输出 window.a 的结果 和执行fun 函数的结果一样

归根结底就是因为 fun 函数在 window对象下调用了!

再看一个例子:

function foo(){
console.log(this.a);
} function fun(){
this.a = "i'm function fun";
console.log(this.a);
} var obj = {
a: "hello i'm a obj",
foo: foo,
fun: fun
} obj.foo();//hello i'm a obj
obj.fun();//i'm function fun

这里定义了一个对象字面量 obj
为obj 设置了一个属性 a,值为:"hello i'm a obj"
然后又定义了两个引用属性:foo 和 fun,他们分别引用 foo函数 和 fun函数

当通过obj 调用 foo函数的时候 输出结果是obj 的a属性值
但调用fun 函数的时候输出结果却是函数内部定义的 a属性值

为什么呢??不是说this 不指向函数本身吗???

-------分隔线-------

别混淆了

上面已经说过 函数里面通过this定义的属性并不是属于函数的作用域
即这个属性并不是函数本身的(虽说js 的函数也是对象 但不带这么玩)

实际上 fun 函数里面this.a 这个语句是为函数当前调用环境对象的属性赋值的语句
通俗的说:
如果,fun函数在 obj 里面调用 this.a 语句就为 obj 对象里面的a 属性赋值
如果,fun函数在 window 对象里面调用 this.a 语句就为 window对象里面的 a属性赋值
如果调用函数的环境下没有匹配的属性 就为其环境创建一个属性并赋值

所以我们得出总结:

 this 对象指向的是函数执行作用域的对象,即函数在哪里执行,this 对象就指向那里!

如果上面的代码你觉得啰嗦,直接记住这一点就好

【笔记】探索js 的this 对象 (第一部分)的更多相关文章

  1. 【笔记】探索js 的this 对象 (第三部分)

    了解完函数的调用区域是如何影响this 对象的,还有this 的各种绑定方式以及各种绑定方式的优先级后 最后一部分,来了解一下this 的一些例外情况 1.被忽略的this 例如在使用bind 方法时 ...

  2. 【笔记】探索js 的this 对象 (第二部分)

    了解this 对象之后 我们明白了this 对象就是指向调用函数的作用域 那么接下来我们便要清除函数究竟在哪个作用域调用 找到调用的作用域首先要了解一下几点: 1.调用栈: 调用栈就是一系列的函数,表 ...

  3. 读书笔记-你不知道的JS上-对象

    好想要对象··· 函数的调用位置不同会造成this绑定对象不同.但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂) 语法 对象声明有两个形式: 1.字面量 => var obj = ...

  4. 超全面的JavaWeb笔记day03<JS对象&函数>

    1.js的String对象(****) 2.js的Array对象 (****) 3.js的Date对象 (****) 获取当前的月 0-11,想要得到准确的月 +1 获取星期时候,星期日是 0 4.j ...

  5. 4月5日--课堂笔记--JS内置对象

    JavaScript 4.5 一.    JS内置对象 1.数组Array a)创建语法1:var arr=new Array(参数); i.       没有参数:创建一个初始容量为0的数组 ii. ...

  6. Node.js学习笔记(四): 全局对象

    在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性. 这 ...

  7. 5月15日上课笔记-js中 location对象的属性、document对象、js内置对象、Date事件对象、

    location的属性: host: 返回当前主机名和端口号 定时函数: setTimeout( ) setInterval() 二.document对象 getElementById(); 根据ID ...

  8. web前端学习(四)JavaScript学习笔记部分(6)-- js内置对象

    1.JS内置对象-什么是对象 1.1.什么是对象: JavaScript中的所有事物都是对象:字符串.数值.数组.函数 每个对象带有属性和方法 JavaScript允许自定义对象 1.2.自定义对象: ...

  9. [Effective Java 读书笔记] 第二章 创建和销毁对象 第一条

    第二章  创建和销毁对象 第一条 使用静态工厂方法替代构造器,原因: 静态工厂方法可以有不同的名字,也就是说,构造器只能通过参数的不同来区分不同的目的,静态工厂在名字上就能表达不同的目的 静态工厂方法 ...

随机推荐

  1. centos7yum安装tomcat

    执行安装命令 [root@localhost ~]# yum -y install tomcat 查询tomcat是否安装成功 [root@localhost ~]# rpm -q tomcat to ...

  2. bzoj 2434 AC自动机 + fail指针建树 + 树状数组

    思路:我们先跟着它给定的字符串走把字典树建出来,求出fail指针,我们考虑两个字符串 A和B, 如果想要求B中有多少A的子串,转换一下就是有多少个B的前缀的后缀包含A,这个在AC自动机 的状态图中很容 ...

  3. sonar rule

    bug类型: 1.".equals()" should not be used to test the values of "Atomic" classes.  ...

  4. sql 时间日期格式化

    sql server2000中使用convert来取得datetime数据类型样式(全) 日期数据格式的处理,两个示例: CONVERT(varchar(16), 时间一, 20) 结果:2007-0 ...

  5. java 中整数类型的进制转换

    int a=10; Integer.toBinaryString(a); //转换成2进制Integer.toOctalString(a);  //转换成8进制Integer.toHexString( ...

  6. Luogu P2486 染色(树链剖分+线段树)

    题解 不妨采取重链剖分的方式把路径剖成区间,然后用线段树维护,考虑如何合并一个区间 struct Node { int lf, rg, tot; }seg[N << 2]; int col ...

  7. hdu 1011(Starship Troopers,树形dp)

    Starship Troopers Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) ...

  8. 通过myEclipse创建hibernate的实体类

    今天有个新项目中需要使用到hibernate,刚好数据库表已经创建完毕,就顺便来总结一下通过myEclipse创建hibernate的实体类. 1..在myEclipse中选择MyEclipse Da ...

  9. 认识C++中的bitset类型

    认识标准库bitset类型 位是用来保存一组项或者条件的yes/no(1或者0)信息的一种简洁方法,那么位集就是二进制位的有序集.C++中标准库提供的bitset类在我们程序中就很有效的简化了对于位集 ...

  10. 【BZOJ 2124】【CodeVS 1283】等差子序列

    http://www.lydsy.com/JudgeOnline/problem.php?id=2124 http://codevs.cn/problem/1283/ 重点是把判断是否存在3个数组成等 ...