javaScript 基础

2019/09/16 javaScript

每一次看 javaScript 都发现有了新的收获

是之前拉下的知识点?是压根就没有看过的?还是知道但是在业务开发的过程中总是忽视忘记了?都有原因吧

哪些我所忽视的 javaScript 基础

  1. 使用”===”替换”==” ,避免隐式转化带来的不必要麻烦,(我以前知道,但是懒得写,以后要这样写了)

每一种基本类型 NumberStringBooleanSymbol 在对象中都有对应的类,所谓的装箱转换就是把基本类型转换为对应的对象类型 一些对性能要求较高的场景下,我们应该尽量避免对基本类型做装箱操作,耗时。非十进制的数字和字符串转换也会有各种问题

拆箱转换 在 JavaScript 标准中,规定了 toPrimitive 函数,他是对象类型到基本类型的转换(拆箱转换) 拆箱转换会尝试调用 valueoftoString 来获得拆箱后的基本类型,如果``valueOftoString` 都不存在或者没有返回基本类型,就会产生类型错误

var o = {
    valueOf:()=>{console.log("valueof");return {}},
    toString:()=>{console.log("toString");return {}}

}
o*2
// valueof
// toString
//Uncaught TypeError: Cannot convert object to primitive value
    at <anonymous>:6:2

String(0)
// toString
// valueof
//Uncaught TypeError: Cannot convert object to primitive value
    at <anonymous>:6:2
  1. JavaScript 中,没有任何方法可以更改私有的class 属性,因此 Object.prototype.toString()是可以准确识别对象对应的基本类型的方法,比 instanceof 更加准确 x s
  2. javascript 具有高度动态性 在 javascript 中对象独有的特色是:对象具有高度的动态性,这是因为 JavaScript 赋予了使用者在运行时为对象添加状态和行为的能力

javascript 对象来说,属性并非只有简单的名称和值,JavaScript 用一组特征来描述属性,数据属性,valuewritableenumerableconfigurable 访问器属性 gettersetterenumberconfigurable。定义属性的时候产生数据属性,代码执行的时候(访问器属性使得属性在读写时执行代码,视为函数的语法糖)(每一次访问属性都会执行 gettersetter 函数)。

对象是一个属性的索引结构(可以以比较快速用 key 来查找 value 的字典)

Javascript 原型系统的复制操作实现思路: 一个并不真的去复制一个原型对象,而是使的新对象持有一个原型的引用

执行上下文

以前我不懂,也不在乎什么是执行上下文,好像并没有什么用,现在我发现我错了。看到一句话 “只有理解了 javaScript 的执行上下文,才能更好的理解 javaScript 语言本身,比如变量提升,作用域,闭包”,关于这些概念不去仔细解释

实际上变量和函数声明在代码里的位置是不会改变的,而是在编译阶段被 javaScript 引擎放入内存中

简单说一段 javaScript 代码可以被分为编译阶段和执行阶段;在编译阶段又可以分为变量提升部分代码(执行上下文)和执行部分代码

执行上下文是 javaScript 执行一段代码时的环境,在执行上下文本中存在一个变量环境的对象(保存变量提升的内容),完了之后javaScript 引擎开始执行可执行代码,一行一行的执行,执行的过程中先在变量环境中查找,找到就输出,找不到就输出 undefined 或者报错

所以说 javaScript 代码在执行前需要先编译,在编译阶段会出现变量提升

注意了: 函数内部通过 var 声明的变量,在编译阶段都被放到了变量环境里面了 通过 let 声明的变量,在编译阶段会被存放到词法环境中 在函数的作用域内部,通过 let 声明的变量会被存放到词法环境的一个单独区域中,这个区域中的变量并不影响作用域外面的变量

作用域链

每一个执行上下文的变量环境中都包含了一个外部引用,用来指向外部的执行上下文(outer),如果一段代码使用了一个变量,javaScript 引擎首先会在“ 当前的执行上下文”中查找该变量,没有找到再继续在 outer 所指向的执行上下文中查找

词法作用域就是指作用域是由代码在函数声明的位置来决定,所以词法作用域是静态作用域,通过它能够预测代码在执行过程中如何查找标识(词法作用域,根据代码位置来决定的)

闭包:如果该闭包会一直使用,那么他可以作为全局变量而存在,如果使用频率不高,而且占用内存又比较大的话,那么就尽量让他成为一个局部变量

通过作用域查找变量的链条称为作用域链,作用域链是通过词法作用域来确定的,而词法作用域反映了代码的结构

作用域链和 this 是两套不同的系统,她们之间基本没有太多联系;this 是和执行上下文绑定的

javaScript 是动态语言,因为在声明变量之前并不需要确认其数据类型,也是弱类型语言,因为支持隐式类型转化

## javaScript 内存空间

javaScript 在执行过程中,主要有三种类型内存空间,代码空间,栈空间,堆空间;

  1. 代码空间: 存储可执行代码的空间
  1. 栈空间:存放原始类型的数据
  1. 堆空间: 存放引用类型的数据

为什么要有栈空间和堆空间? 因为 javaScript 引擎需要用栈来维护程序执行期间的上下文状态,如果栈空间大了的话,所有数据都放在栈空间里面,那么会影响到上下文切换效率,从而影响整个程序的执行效率。所以栈空间都不会设置太大,主要用来放一些原始类型的小数据。er引用类型的数据占用的空间都比较大,所以会被放到堆中。

原始类型的赋值会完整的复制变量值,而引用类型的赋值是复制引用地址。闭包是存储在堆内存中的

编译器和解释器

之所以存在是因为机器不能直接理解我们所写的代码,所以在执行程序之前,需要将我们所写的代码翻译成机器能读懂的机器语言,按照语言的执行流程可以划分为编译型语言和解释型语言。编译型语言:需要经过编译器的编译过程,编译后直接保留机器能够读懂的二进制文件;解释型语言:每一次运行都需要通过解释器对程序进行动态解释和执行


一名伪程序猿——sunseekers,曾被bug虐的体无完肤,却依旧待他如初恋。

如果我改过的某一个bug,吐槽过的某一个需求,写过的某一行代码

曾在你的心里荡起涟漪,那至少说明在逝去的岁月里,我们在某一刻,共同经历着一样的情愫。

有时候,虽然素未谋面。却已相识很久,很微妙也很知足。


如果你喜欢我写过的某一个文字,请支持我,鼓励我,你的鼓励是我最大的动力来源

当然恰好你也喜欢我的话,我们可以互相关注,相互学习的哟!

sunseekers

Search

    Table of Contents