js深入(四)万脸懵圈的this指向
作为一个js菜鸡的我而言,在之前讲到过那么多的js链式查找机制,比如说原型链,作用域链等等,想当然的把这个机制带入到了this指向上边,结果就是这个this指向指的我万脸懵逼(标题换字了,担心被河蟹),在经过漫长的通(gou)俗(pi)易(bu)懂(tong)的 ECMAScript规范阅读之后,分享一下我所认知的this指向
简而言之,js中this的指向不是在函数定义的时候确定的,而是在调用的时候创建阶段确定的,也就是说this指向谁,完全取决于函数的调用方式
常见的几种调用方式
直接调用, 比如说
function a() {
console.log(this);
} a();
这个例子里边this指向的是全局对象,在客户端的全局对象是window对象,在node 中的全局对象是global对象
(function a() {
function b() {
console.log(this);
}
b()
})()
直接调用指的是直接用函数名称后边加()执行调用的函数,无论是否在全局作用域
间接调用
const obj ={
name:'obj对象',
a(){
console.log(this)
}
}
obj.a()
如图
在图中我们可以看到我们在对象里边调用对象里边的方法的时候,this指向的是obj对象,
或者说外边有一个函数 然后给一个obj对象的属性赋值
const obj ={
name:'obj对象',
a(){
console.log(this)
}
}
obj.a()
obj.b=function(){
console.log(this,'b')
}
obj.b()
打印的结果都是obj对象
- new调用
当我们他用过new 创建一个新的对象的时候,new会调用这个构造函数来创建一个对象,那么这个对象里边的this是这个被new的函数调用的,那么自然 new调用的时候,this就是指向这个新对象的
function A(data) {
this.data = data;
}
class B{
constructor(data){
this.data = data
}
}
let a = new A("A");
let b = new B("B");
console.log(a.data);
console.log(b.data);
如图
这个new,在创建对象的时候做了什么,我们会在下一篇博客里边仔细说明
- 箭头函数中的this
箭头函数可以理解成是是一个语法糖,他没有自己的this绑定,箭头函数中使用的this是包含他的那个函数的this
比如说
const obj = {
a() {
return () => {
console.log(this);
};
}
}
上边这段代码被转译成es5 的时候如下
const obj = {
a: function a() {
var _this = this;
return function () {
console.log(_this);
};
}
};
综合以上所有的代码,得出一个结论就是,在js中this的绑定正常来讲是指向调用这个方法的对象来确定的,当然还有一些不正常的方法,可以改变this的指向
注意 ,下边介绍的几种方法,不能改变箭头函数的this指向,箭头函数本身是没有this绑定的,在介绍完不正常的情况后,再来说一说那些能够改变this指向的方法
ECMAScript 5.1 规范的this指向
js中this的绑定正常来讲是指向调用这个方法的对象来确定的
这句话在理论上是这么讲,在工作中正常的调用的话,这个理论是没有毛病的,在 ECMAScript 5.1 的规范里边规定,在js里边分为语言类型和规范类型
- 语言类型
ECMAScript 里边的语言类型规定的是我们可以直接操作的一些类型,比如string number,object等等这些
- 规范类型
规范类型ECMAScript 里边指的是一种抽象的规范,他们并不是让我们用来进行操作的,二是用来描述一些行为或者逻辑的,比如说typeof delete等等
ECMAScript 5.1 里边的this规定大概讲就是这样的,每个对象里边有一个Reference 规范类型,this会根据Reference这个规范类型进行赋值
规范奉上 Reference 这个东西大家简单的理解成是()前边的那一块就好了,上边我们讲的那些正常的就是说左边是
- 函数定义表达式
- 属性访问表达式
- 对象创建表达式
- 属性创建表达式
这几种情况,在这几种情况的时候上边那句话是成立的
但是如果不是这上边的那几句话的时候,比如说括号里边是一个和函数相关计算或者一个运算符等等
这个时候this会指向undefined ,这个时候在非严格模式的情况下会被隐式转换成window对象
var value = 1;
var obj = {
value: 2,
a() {
return this.value;
}
}
console.log(obj.a());
console.log((obj.a)());
console.log((obj.a = obj.a)());
console.log((false || obj.a)());
console.log((obj.a, obj.a)());
记得之前看到过这个一个例子,运行结果如图
时间关系就说这些,下一篇博客会说new在运行时候过程和改变this指向的一些方法,
以上是我对this指向的一些认识,有不足的地方希望之处
js深入(四)万脸懵圈的this指向的更多相关文章
- 前端总结·基础篇·JS(四)异步请求及跨域方案
前端总结系列 前端总结·基础篇·CSS(一)布局 前端总结·基础篇·CSS(二)视觉 前端总结·基础篇·CSS(三)补充 前端总结·基础篇·JS(一)原型.原型链.构造函数和字符串(String) 前 ...
- 玩转Node.js(四)-搭建简单的聊天室
玩转Node.js(四)-搭建简单的聊天室 Nodejs好久没有跟进了,最近想用它搞一个聊天室,然后便偶遇了socket.io这个东东,说是可以用它来简单的实现实时双向的基于事件的通讯机制.我便看了一 ...
- js 第四章 cookie的操作
js 第四章 cookie的操作 一.学习要点 掌握cookie的简单应用 二. js 第四章 cookie的操作 了解cookie 什么是cookie? cookie 是存储于访问者的计算机中的变量 ...
- 面试官问:HashMap在并发情况下为什么造成死循环?一脸懵
这个问题是在面试时常问的几个问题,一般在问这个问题之前会问Hashmap和HashTable的区别?面试者一般会回答:hashtable是线程安全的,hashmap是线程不安全的. 那么面试官就会紧接 ...
- bootstrap学习总结-js组件(四)
这次我们来看下js组件的使用,本篇文章会有点长,希望大家可以耐心看,相信收获会有不少.不少园友加我好友,表示喜欢我写文字的风格,简单明了,这里,再次谢谢你们的支持.一方面,博主自身技术有限,写的东西都 ...
- JavaScript--我发现,原来你是这样的JS(四)(看看变量,作用域,垃圾回收机制是啥)
一.介绍 这是红宝书(JavaScript高级程序设计 3版)的读书笔记第四篇,是红宝书第四章内容(主要是变量和作用域问题),当然其中还有我个人的理解.红宝书这本书可以说是难啃的,要看完不容易,挺厚的 ...
- JS正则四个反斜杠的含义
我们首先来看如下代码,在浏览器中输出的是什么? // 在浏览器中输出的 console.log('\\'); // 输出 \ console.log('\\\\'); // 输出 \\ 一:js正则直 ...
- node.js(基础四)_express基础
一.前言 本次内容主要包括: 1.express的基本用法 2.express中的静 ...
- js第四天学习小结:
(1)函数的四种形式小结: 无参无返回值 function tellstory(){ console.log("从前有座山"); console.log(" ...
随机推荐
- WPF与缓动(四) 弧形缓动
原文:WPF与缓动(四) 弧形缓动 WPF与缓动(四) 弧形缓动 ...
- Lexer的设计--上(3)
lexer的构造函数 有了上一节Token做铺垫, 可以开始设计lexer, 首先应该想到的是, 源代码是以文件流的格式传到编译器中的, 所以作为编译器的前段的第一个阶段, lexer必须负责处理输入 ...
- git 创建一个空分支
创建一个分支 使用参数 --orphan,这个参数的主要作用有两个,一个是拷贝当前所在分支的所有文件,另一个是没有父结点,可以理解为没有历史记录,是一个完全独立背景干净的分支. 参考git的帮助文档, ...
- 如何将编码转为自己想要的编码 -- gbk utf-8
/** * 数组转码 * @param array $arr 要转码的数组 * @param string $in_charset 输入的字符集 * @param string $out_ch ...
- DataGridView 中发生以下异常: System.Exception: 是 不是 Decimal 的有效值。 ---> System.FormatException: 输入字符串的格式不正确。
其实之前我自己是没测出这个问题的,但是一放到测试的手上就出来了,原因我知道在哪里改输什么东西,但是人家不知道啊.报错如下: --------------------------- “DataGridV ...
- 零元学Expression Blend 4 - Chapter 14 用实例了解布局容器系列-「Pathlistbox」II
原文:零元学Expression Blend 4 - Chapter 14 用实例了解布局容器系列-「Pathlistbox」II 本章将延续上一章的范例,步骤解析. 本章将延续上一章的范例,步骤解析 ...
- UWP入门(九)-- 枚举和查询文件和文件夹
原文:UWP入门(九)-- 枚举和查询文件和文件夹 核心 API 所在的命名空间: Windows.Storage Windows.Storage.Streams Windows.Storage.Pi ...
- 读取注册表获取Windows系统XP/7/8/10类型(使用wcscmp比较wchar[]内容)
很多方案是采用GetVersion.GetVersionEx这两个API来查询操作系统的版本号来判断当前的操作系统是Windows系列中的哪个,在Win10没有出现前,这种方法是行的通的,但是Win1 ...
- C++虚函数表解析(图文并茂,非常清楚)( 任何妄图使用父类指针想调用子类中的未覆盖父类的成员函数的行为都会被编译器视为非法)good
C++中的虚函数的作用主要是实现了多态的机制.关于多态,简而言之就是用父类型别的指针指向其子类的实例,然后通过父类的指针调用实际子类的成员函数.这种技术可以让父类的指针有“多种形态”,这是一种泛型技术 ...
- qt 维护x86和arm两套编译环境
1.中间库: 中间库都放在middlewares目录,include头文件相同,所以不需要特殊处理,只要特殊处理lib安装目录, 示例pro文件如下: TEMPLATE = lib TARGET = ...