最近在看 你不知道的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. Linux下源码安装jdk

    1.到官网下载 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

  2. AC日记——[POI2014]KUR-Couriers 洛谷 P3567

    [POI2014]KUR-Couriers 思路: 卡空间,sb题: 代码: #include <bits/stdc++.h> using namespace std; #define m ...

  3. 安装jdk8-linux版

    下载jdk http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 安装 rpm -iv ...

  4. C/C++宏的用法

    今天看caffe源码的时候看到了很多宏定义的内容,苦于代码基础薄弱,无法全部理解,故在网上搜得此篇好文,转载一发附原文地址:http://blog.csdn.net/hanchaoman/articl ...

  5. Python WindowsError

    WindowsError: [Error 2] The system cannot find the file specified WindowsError: [Error 3] The system ...

  6. 安装 gcc 编译器

    1.安装编译工具 gcc.gcc-c++.make 注意解决依赖关系,推荐使用 yum 安装,若不能联网可使用安装光 盘做为 yum 源 1)编辑 yum 配置文件: Mount /dev/cdrom ...

  7. Spring Cloud Eureka 总结

    写在前面的话(给自己) 为了巩固自身学习,从今天(2019.01.08),每天晚上开始总结SpringCloud的相关学习,用于自我勉励,自我积累与人生总结. 总结2018年的我,心态较之从前浮躁,杂 ...

  8. Luogu P2016 战略游戏(树形DP)

    题解 设\(f[u][0/1/2]\)表示当前节点\(u\),放或不放(\(0/1\))时其子树满足题目要求的最小代价,\(2\)表示\(0/1\)中的最小值. 则有: \[ f[u][0]=\sum ...

  9. 洛谷——P1618 三连击(升级版)

    P1618 三连击(升级版) 题目描述 将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”. //感谢 ...

  10. BZOJ 4443 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)

    [题目链接]http://www.lydsy.com/JudgeOnline/problem.php?id=4443 [题目大意] 从矩阵中选出N个数,其中任意两个数字不能在同一行或同一列 求选出来的 ...