JavaScript 知识框架一

JS目录

给 JavaScript 做一个顶层目录,可这样划分:文法、语义、运行时
再细分为:


建立知识框架

两个目标:一是理解原理和背景,二是把不方便查阅和记忆的内容整理好
前端知识在总体上分成基础部分和实践部分
基础部分包含3大块: JS语言、CSS 及 HTML、浏览器的实现原理及API

一、类型

JS分7 种类型是:

Undefined;Null;Boolean;String;Number;Symbol;Object
Undefined与null

Undefined 类型表示未定义,它的类型只有一个值,就是 undefined。任何变量在赋值前是 Undefined 类型、值为 undefined
编程规范要求用 void 0 代替 undefined,因为:JS 的代码 undefined 是一个变量,而并非是一个关键字,这是 js 语言公认的设计失误之一,所以,为了避免无意中被篡改,建议用 void 0 来获取 undefined 值
Undefined 跟 Null 有一定的表意差别,Null 表示的是:“定义了但是为空”。
Null与 undefined 不同,null 是 JavaScript 关键字,所以在任何代码中,你都可以放心用 null 关键字来获取 null 值。

String

String 用于表示文本数据。String 有最大长度是 2^53 - 1。
String 的意义并非“字符串”,而是字符串的 UTF16 编码
字符串的操作 charAt、charCodeAt、length 等方法针对的都是 UTF16 编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。
JavaScript 中的字符串是永远无法变更的,一旦字符串构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征。

Number

JavaScript 为了表达几个额外的语言场景(比如不让除以 0 出错,而引入了无穷大的概念)

规定了几个例外情况:
NaN,占用了 9007199254740990,它不是个数字
Infinity,无穷大;
-Infinity,负无穷大。

Symbol

Symbol 是 ES6 中引入的新类型,它是一切非字符串的对象 key 的集合
在 ES6 规范中,整个对象系统被用 Symbol 重塑。
我们创建 Symbol 的方式是使用全局的 Symbol 函数。
例如: var mySymbol = Symbol("my symbol");

Object

Object 的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是 key-value 结构,key 可以是字符串或者 Symbol 类型。
我们必须认识到 3 与 new Number(3) 是完全不同的值,它们一个是 Number 类型, 一个是对象类型。
因为 C++ 和 Java 的成功,在这两门语言中,每个类都是一个类型,二者几乎等同,以至于很多人常常会把 JavaScript 的“类”与类型混淆。
Number、String 和 Boolean,三个构造器是两用的,当跟 new 搭配时,它们产生对象,当直接调用时,它们表示强制类型转换。
Symbol 函数比较特殊,直接用 new 调用它会抛出错误,但它仍然是 Symbol 对象的构造器。

JavaScript 中的“类”仅仅是运行时对象的一个私有属性,而 JavaScript 中是无法自定义类型的。
JS 语言设计上试图模糊对象和基本类型之间的关系,可以把对象的方法在基本类型上使用
比如: console.log("abc".charAt(0)); //a
其原理是,. 点运算符提供了装箱操作,它会根据基础类型构造一个临时对象,能在基础类型上调用对应对象的方法

二、装箱、拆箱

前文提到,全局的 Symbol 函数无法使用 new 来调用,但我们仍可以利用装箱机制来得到一个 Symbol 对象,我们可以利用一个函数的 call 方法来强迫产生装箱。

var symbolObject = (function(){ return this; }).call(Symbol("a"));

使用内置的 Object 函数,我们可以在 JS 中显式调用装箱能力

var symbolObject = Object(Symbol("a")); 
console.log(typeof symbolObject); //object

拆箱转换
拆箱转换,它是对象类型到基本类型的转换。
会尝试调用 valueOf 和 toString 来获得拆箱后的基本类型。如果 valueOf 和 toString 都不存在,或者没有返回基本类型,则会产生类型错误 TypeError。
在 ES6 之后,还允许对象通过显式指定 Symbol.toPrimitive 来覆盖原有的行为(用这方法就不会执行valueOf和toString方法)


三、对象属性:

对象属性分为:数据属性、访问器属性
数据属性:它比较接近于其它语言的属性概念,具有四个特征

value:就是属性的值。
writable:决定属性能否被赋值。
enumerable:决定 for in 能否枚举该属性。
configurable:决定该属性能否被删除或者改变特征值。

在大多数情况下,我们只关心数据属性的值即可

访问器属性:
属性在读和写时执行,它允许使用者在写和读属性时,得到完全不同的值,可视为一种函数的语法糖

getter:函数或 undefined,在取属性值时被调用。
setter:函数或 undefined,在设置属性值时被调用。
enumerable:决定 for in 能否枚举该属性。
configurable:决定该属性能否被删除或者改变特征值。
对象分类

1、宿主对象(host Objects):由 JavaScript 宿主环境提供的对象,它们的行为完全由宿主环境决定。
2、内置对象(Built-in Objects):由 JavaScript 语言提供的对象。

  • 2.1、固有对象(Intrinsic Objects ):由标准规定,随着 JavaScript 运行时创建而自动创建的对象实例。
  • 2.2、原生对象(Native Objects):可以由用户通过 Array、RegExp 等内置构造器或者特殊语法创建的对象。
  • 2.3、普通对象(Ordinary Objects):由{}语法、Object 构造器或者 class 关键字定义类创建的对象,它能够被原型继承。

宿主对象,分为固有宿主的和用户可创建的宿主两种
固有宿主如:window
用户创建宿主如: document.createElement 就可以创建一些 DOM 对象

固有对象,在任何 JavaScript 代码执行前就已经被创建出来了,它们通常扮演者类似基础库的角色

三个值:Infinity、NaN、undefined
九个函数:eval、isFinite、isNaN、parseFloat、parselnt、decodeURl、decodeURIComponent、encodeURI、encodeURlComponent
构造器:Array、Date、RegExp、Promise、Proxy、Map、WeakMap、Set、WeakSet、Function、Boolean、String、Number、Symbol、Object、Error、EvalError....
四个用于当作命名空间的对象:Atomics、JSON、Math、Reflect

原生对象,分成以下类:

JavaScript 用对象模拟函数的设计代替了一般编程语言中的函数,它们可以像其它语言的函数一样被调用、传参。
任何对象只需要实现[[call]],它就是一个函数对象,可以去作为函数被调用。而如果它能实现[[construct]],它就是一个构造器对象,可以作为构造器被调用。
用户用 function 关键字创建的函数必定同时是函数和构造器,但它们表现出来的行为效果却并不相同。


JS 的执行

Promise:是 JavaScript 语言提供的一种标准化的异步管理方式,它的总体思想是,需要进行 io、等待或者其它异步操作的函数,不返回真实结果,而返回一个“承诺”,函数的调用方可以在合适的时机,选择等待这个承诺兑现(通过 Promise 的 then 方法的回调)

var r = new Promise(function(resolve, reject){ 
    console.log("a"); 
    resolve() 
}); 
setTimeout(()=>console.log("d"), 0)  //0秒的setTimeout
r.then(() => console.log("c"));  
console.log("b")

打印顺序是abcd,不论代码顺序如何,d 必定发生在 c 之后,哪怕Promise返回需要3秒,也仍然是先c后d。
因为 Promise 产生的是 JavaScript 引擎内部的微任务,而 setTimeout 是浏览器 API,它产生宏任务。

generator/iterator 也常常被跟异步一起来讲,但它们并非异步代码,只是在缺少 async/await 的时候,一些框架使用这样的特性来模拟 async/await。但是 generator 并非被设计成实现异步,所以有了 async/await 之后,generator/iterator 就不应用来模拟异步的方法,只用于迭代器。

通常把宿主发起的任务称为宏观任务,JS引擎发起的任务称为微观任务
Promise 产生异步代码,JS保证这些异步代码在一个宏观任务中完成 (每个宏观任务包含1个微观任务队列)
异步执行的顺序:
1、首先我们分析有多少个宏任务;
2、在每个宏任务中,分析有多少个微任务;
3、根据调用次序,确定宏任务中的微任务执行次序;
4、根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
5、确定整个顺序


在只有 var,没有 let 的旧 JavaScript 时代,诞生了一个技巧,叫做:立即执行的函数表达式(IIFE),通过创建一个函数,并且立即执行,来构造一个新的域,从而控制 var 的范围。

(function(){ 
  var a;
}());
或者
(function(){ 
  var a; 
})();
推荐用法:
void function(){
 var a; 
}();

有了let,就不需要用这种立即执行函数了

执行上下文

一旦上下文被切换,整个语句的效果可能都会发生改变。所以切换上下文的时机就显得非常重要。切换上下文最主要的场景是函数调用。

1、看个简单的切换上下文代码:

//a.js
var a = 1;
function foo(){ 
  console.log(a); 
  console.log(b);  
}

//b.js
引入a.js
var b = 2;
foo();    //这里就是切换上下文
foo打印a 为1,打印b 报错

看以下的这段 JS代码:

var b = {}
let c = 1
this.a = 2; 
//1、var 把 b 声明到哪里;
//2、b 表示哪个变量;
//3、b 的原型是哪个对象;
//4、let 把 c 声明到哪里;
//5、this 指向哪个对象

2、回答上面的问题,先从理解this关键字开始
this 是执行上下文中很重要的一个组成部分。同一个函数调用方式不同,得到的 this 值也不同
this 跟面向对象毫无关联,它是与函数调用时使用的表达式相关

普通函数的 this 值由 ‘ 调用它所使用的引用 ’ 决定,下面示例

function showThis(){
  console.log(this);
}
var o = { 
  x:2,
  showThis: showThis
}
showThis(); // global
o.showThis(); // Reference 类型 o   //{ x: 2, showThis: [Function: showThis] } 

注意:上面获取函数的表达式,它返回的并非函数本身,而是一个 Reference 类型
Reference 类型由两部分组成:一个对象和一个属性值
上面代码中 o.showThis 产生的 Reference 类型,即由对象 o 和属性“showThis”构成

3、JavaScript 用一个栈来管理执行上下文,这个栈中的每一项又包含一个链表。如下图所示:



当函数调用时,会入栈一个新的执行上下文,函数调用结束时,执行上下文被出栈。
而 this 则是一个更为复杂的机制

4、操作 this 的内置函数
Function.prototype.call 和 Function.prototype.apply 可以指定函数调用时传入的 this 值

function foo(a, b, c) {
  console.log(this)
  console.log(a, b, c)
}
foo(1, 2, 3) //this为 global
foo.call({}, 1, 2, 3) //this为{}
foo.apply({}, [1, 2, 3]) //this为{}
call 和 apply 作用是一样的,只是传参方式有区别

来源: winter 老师的 重学前端

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,968评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,601评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,220评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,416评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,425评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,144评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,432评论 3 401
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,088评论 0 261
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,586评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,028评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,137评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,783评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,343评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,333评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,559评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,595评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,901评论 2 345

推荐阅读更多精彩内容