【笔记】探索js 的this 对象 (第一部分)
最近在看 你不知道的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 对象 (第一部分)的更多相关文章
- 【笔记】探索js 的this 对象 (第三部分)
了解完函数的调用区域是如何影响this 对象的,还有this 的各种绑定方式以及各种绑定方式的优先级后 最后一部分,来了解一下this 的一些例外情况 1.被忽略的this 例如在使用bind 方法时 ...
- 【笔记】探索js 的this 对象 (第二部分)
了解this 对象之后 我们明白了this 对象就是指向调用函数的作用域 那么接下来我们便要清除函数究竟在哪个作用域调用 找到调用的作用域首先要了解一下几点: 1.调用栈: 调用栈就是一系列的函数,表 ...
- 读书笔记-你不知道的JS上-对象
好想要对象··· 函数的调用位置不同会造成this绑定对象不同.但是对象到底是什么,为什么要绑定他们呢?(可以可以,我也不太懂) 语法 对象声明有两个形式: 1.字面量 => var obj = ...
- 超全面的JavaWeb笔记day03<JS对象&函数>
1.js的String对象(****) 2.js的Array对象 (****) 3.js的Date对象 (****) 获取当前的月 0-11,想要得到准确的月 +1 获取星期时候,星期日是 0 4.j ...
- 4月5日--课堂笔记--JS内置对象
JavaScript 4.5 一. JS内置对象 1.数组Array a)创建语法1:var arr=new Array(参数); i. 没有参数:创建一个初始容量为0的数组 ii. ...
- Node.js学习笔记(四): 全局对象
在浏览器 JavaScript 中,通常 window 是全局对象, 而 Node.js 中的全局对象是 global,所有全局变量(除了 global 本身以外)都是 global 对象的属性. 这 ...
- 5月15日上课笔记-js中 location对象的属性、document对象、js内置对象、Date事件对象、
location的属性: host: 返回当前主机名和端口号 定时函数: setTimeout( ) setInterval() 二.document对象 getElementById(); 根据ID ...
- web前端学习(四)JavaScript学习笔记部分(6)-- js内置对象
1.JS内置对象-什么是对象 1.1.什么是对象: JavaScript中的所有事物都是对象:字符串.数值.数组.函数 每个对象带有属性和方法 JavaScript允许自定义对象 1.2.自定义对象: ...
- [Effective Java 读书笔记] 第二章 创建和销毁对象 第一条
第二章 创建和销毁对象 第一条 使用静态工厂方法替代构造器,原因: 静态工厂方法可以有不同的名字,也就是说,构造器只能通过参数的不同来区分不同的目的,静态工厂在名字上就能表达不同的目的 静态工厂方法 ...
随机推荐
- Linux下源码安装jdk
1.到官网下载 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
- AC日记——[POI2014]KUR-Couriers 洛谷 P3567
[POI2014]KUR-Couriers 思路: 卡空间,sb题: 代码: #include <bits/stdc++.h> using namespace std; #define m ...
- 安装jdk8-linux版
下载jdk http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html 安装 rpm -iv ...
- C/C++宏的用法
今天看caffe源码的时候看到了很多宏定义的内容,苦于代码基础薄弱,无法全部理解,故在网上搜得此篇好文,转载一发附原文地址:http://blog.csdn.net/hanchaoman/articl ...
- Python WindowsError
WindowsError: [Error 2] The system cannot find the file specified WindowsError: [Error 3] The system ...
- 安装 gcc 编译器
1.安装编译工具 gcc.gcc-c++.make 注意解决依赖关系,推荐使用 yum 安装,若不能联网可使用安装光 盘做为 yum 源 1)编辑 yum 配置文件: Mount /dev/cdrom ...
- Spring Cloud Eureka 总结
写在前面的话(给自己) 为了巩固自身学习,从今天(2019.01.08),每天晚上开始总结SpringCloud的相关学习,用于自我勉励,自我积累与人生总结. 总结2018年的我,心态较之从前浮躁,杂 ...
- Luogu P2016 战略游戏(树形DP)
题解 设\(f[u][0/1/2]\)表示当前节点\(u\),放或不放(\(0/1\))时其子树满足题目要求的最小代价,\(2\)表示\(0/1\)中的最小值. 则有: \[ f[u][0]=\sum ...
- 洛谷——P1618 三连击(升级版)
P1618 三连击(升级版) 题目描述 将1,2,…,9共9个数分成三组,分别组成三个三位数,且使这三个三位数的比例是A:B:C,试求出所有满足条件的三个三位数,若无解,输出“No!!!”. //感谢 ...
- BZOJ 4443 [Scoi2015]小凸玩矩阵(二分答案+二分图匹配)
[题目链接]http://www.lydsy.com/JudgeOnline/problem.php?id=4443 [题目大意] 从矩阵中选出N个数,其中任意两个数字不能在同一行或同一列 求选出来的 ...