从白纸一张到现在算有些经验的前端开发,经过了两个春秋了。一直在社区吸取知识,却也没写过什么文章。2020年立个flag,每周两篇的技术文章分享,希望自己可以坚持吧!掘金大牛那么多,如果有什么地方理解有误的,希望大家斧正!
这一系列是自己在又又又一次尝试通读红宝书的过程中学到的东西或者在日常开发中总是忽略的内容,废话不多数,来干货啦!
基本类型与引用类型的值
js变量不同于其他语言的变量,由于没有数据类型的限制,我们在脚本的生命周期中改变变量的值和数据类型。众所周知,js变量可以包含两种数据类型的值:基本类型值和引用类型值,基本数据类型是按值访问的,我们操作的是保存在变量中的实际的值。而是引用类型的值是保存在内存中的对象,js不允许直接操作对象的内存空间,所以我们能操作的实际上只是对象的引用。(当我们复制保存了对象的变量时,操作的是引用,但在为对象添加属性时,操作的是实际的对象); 以下列出基本类型与引用类型的几点基本的不同之处
- 我们只能对引用类型动态添加属性和方法,给基本类型添加虽不会报错,但也无法访问。
- 复制变量值时,基本类型会先创建一个新值,然后赋值给新变量,引用类型则只是复制一个指针,该指针指向堆中的一个对象,实际上两个变量将引用同一个对象,改变其中一个,就会影响另一个变量。
引用类型和基本类型参数的传递
在js中,所有参数都是按值传递的,也就是函数外部的值会被复制给一个局部变量(命名参数,即arguments对象中的一个元素)。在向参数传递引用类型的值时,会把这个值在内存中的地址复制给局部变量,所以该局部变量的变化也会影响函数外部的变量。如下:
function setName(obj){
obj.name = 'x'
};
const person = new Object();
setName(person);
console.log(person.name); // 'x'
引用类型在参数传递时是按值传递,但在局部作用域的修改会影响全局变量,很多人不能理解,我从红宝书上理解到的是,虽然是按值传递的,但值是该变量在内存中的地址,当我们在函数内部改变参数的值时,原始的引用仍在,所以会影响全局变量 。当我们在内部重写参数时,此时的参数引用的就是一个局部变量了,且会在函数执行完毕后销毁。
数据类型检测
typeof 是检测基本类型的绝佳工具,但在检测引用类型时,这个操作符就无大用处了。
typeof string // string
typeof number // number
typeof undefined // undefined
typeof boolean // boolean
typeof null // object
typeof object // object
如果我们想要知道变量是什么类型的对象,我们可以使用instanceof操作符,返回布尔值:
person instanceof Object // 变量是Object吗?
person instanceof Array // 变量是array吗?
person instanceof Function // 变量是Function吗?
执行环境及作用域
执行环境是JavaScript中最重要的一个概念。执行环境定义了变量或函数有权访问的数据。每个执行环境都有一个与之关联的变量对象,环境中定义的变量和函数都保存在该对象中(我们在代码中无法访问该对象,解析器在后台会用到它);执行环境分为全局和局部(函数) 全局执行环境时最外围的执行环境,由js所在的宿主环境决定,在web浏览器中,被认为是window对象。某个执行环境中的所有代码执行完毕后,该环境被销毁,保存的变量和函数也随之销毁(全局执行环境直到应用退出-如关闭网页 才会被销毁)
每个函数都有自己的执行环境(局部),当执行流进入一个函数时,函数的执行环境就会被推入一个环境栈中,在函数执行之后,栈将其执行环境弹出,并将控制权交给之前的执行环境。
当代码在某一个执行环境中执行时,会创建变量对象的作用域链,而作用域的最前端,始终是当前执行的代码所在执行环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象,活动对象最开始只有arguments(全局情况下不存在),作用域链的下一个变量对象来自包含环境,下一个变量对象赖在下一个包含环境,直至全局执行环境。而解析标识符(变量)识沿着作用域链一级一级搜索的,且始终从最前端开始。
今天就写到这里啦,望各位看官不吝赐教!