最近在看 你不知道的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. cordova plugin 大全及安装命令

    前言:用cordova开发hybrid app的过程中,由于是html5开发的app,在手机上很多权限受限制,这就导致了我们需要安装很多插件来弥补这一缺点.在网上搜了好久,感觉都不是很全,所以自己整理 ...

  2. js对象替换键值名称

    js对象替换键值名称 将obj中的id和name字段替换分别替换成为“@id”,“@name” 代码如下: let obj = [{id:,name:,name:"李四"}].ma ...

  3. Ubuntu上开启Apache Rewrite功能的方法

    Ubuntu上开启Apache Rewrite功能的方法 本文介绍ubuntn系统中开启apache的urlrewrite功能的方法. 在Windows上开启Apache的urlRewrite非常简单 ...

  4. [scrapy] scrapy 使用goose作为正文提取

    import scrapy from goose import Goose class Article(scrapy.Item): title = scrapy.Field() text = scra ...

  5. IoC控制反转和DI依赖注入

    控制反转(Inversion of Control,英文缩写为IoC)是框架的重要特征,并非面向对象编程的专用术语.它与依赖注入(Dependency           Injection,简称DI ...

  6. Xamarin中VS无法连接Mac系统的解决办法

    Xamarin中VS无法连接Mac系统的解决办法 按照以下步骤排查:(1)确认Mac系统中安装Xamarin.iOS开发必备的组件,如Mono.Xamarin.iOS.(2)将Windows和Mac下 ...

  7. run()和start()的区别

    run没有启新的线程,start方法才会调用Thread的native的start0方法,start0会调用run方法,开启新的线程,博主这么做,不是多线程顺序执行,而是把业务阻塞在主线程里.请打印: ...

  8. [BZOJ 1562] 变换序列

    Link: BZOJ 1562 传送门 Solution: 一道比较考对$Hungry$算法理解的题目 首先可以轻松看出原序列和答案序列的对应关系,从而建出二分图匹配模型 下面的关键在于如何保证字典序 ...

  9. 【状压dp】Travelling

    [hdu3001]Travelling Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  10. Erlang学习记录(一)——Windows下的环境搭建

    一.安装编译器 在http://www.erlang.org/download.html下载R16B01 Windows Binary File并安装. 二.运行编译器 安装完编译器后,打开安装目录下 ...