IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 变量、作用域与内存 -> 正文阅读

[JavaScript知识库]变量、作用域与内存

变量、作用域与内存

数据类型

基本数据类型(原始值)

1》undefined

2》null

3》boolean

true、false

4》string

字符串不可变:想要修改某个变量中字符串的值,就必须销毁原来字符串,然后将新值保存到该变量

5》number

6》symbol

复杂数据类型

Object----对象

我们的变量可能存储的时基本数据类型,基本类型存储在栈中,此时的变量类型就是原始值,

也有可能存的是复杂数据类型,复杂数据类型存放在堆中,此时变量名存的是对应复杂数据的引用地址

深克隆与浅克隆

将一个变量赋值给另一个变量,如果是简单数据类型,由于它存的是数据的原始值,会将原始值复制一份,然后存在另一个变量中;复制后两者相互独立互补影响

浅克隆:一个修改,另一个也受影响

      let num1 = 10;
      let num2 = num1;
      console.log(num2); // 10
      num2 = 20;
      console.log(num1, num2); // 10,20

但是对于复杂数据类型,由于变量存的是复杂数据的引用地址,将一个变量复制给另一个变量时,复制的时应用地址,所以修改一个变量的内容,另一个也跟着改变

深克隆:克隆后相互独立,互不影响

      let obj1 = { name: "马什么梅" };
      let obj2 = obj1;
      console.log(obj2); // { name: "马什么梅" }
      obj2.name = "马冬梅";
      console.log(obj1.name, obj2.name); // 马冬梅 马冬梅

实现深克隆最实用的方法就是 :

   JSON.parse(JSON.stringify(obj))

typeof与instanceof类型判断

typeof

typeof检测原始类型(基本数据类型)的具体类型

返回值:数据的类型; 如果是null,返回的是object

      console.log(typeof 666); // number

      console.log(typeof "nb"); // string

      console.log(typeof true); // boolean

      console.log(typeof undefined); // undefined

      console.log(typeof null); // object

      console.log(typeof [1, 2]); // object

      console.log(typeof { content: "hi" }); // object

      const func = () => {

        console.log("月亮不睡我不睡");

      };

      console.log(typeof func); // function

检测基本数据类型,返回的是具体数据类型,但是null返回的是object;检测引用类型的时候,返回的是object,但是函数返回的是object

补充:任何实现内部使用了call方法的对象,使用typeof都返回function,比如正则表达式;在Chrome7和Safari5及之前版本,上述浏览器的正则表达式内部实现使用了call,但是后面都是返回object了

instanceof

适用于检测引用类型的具体类型

返回值:布尔值

自己定义的构造函数,new 出来的实例,也可以检测

      console.log([1, 2] instanceof Array); //true

      console.log({ content: "hi" } instanceof Object); //true

      const fn = () => {

        console.log("我是秃头小宝贝");

      };

      console.log(fn instanceof Function); //true

      console.log([1, 2] instanceof Object); //true

      console.log({ content: "hi" } instanceof Array); //false

      function Person(name) {

        this.name = name;

      }

      const p = new Person("luka");

      console.log(p instanceof Person); //true

      // instanceof不能检测基本数据类型

      console.log(66 instanceof Number); //false

      console.log(null instanceof Object); //false

执行上下文与作用域链

上下文

上下文有全局上下文和函数上下文,函数上下文是在函数被调用的时候产生的;

      var globalValue = "shake you body";
      function greet() {
        alert("hello");
      }
      greet();

首先全局上下文进栈,greet被调用时,产生一个函数上下文,进入栈中

上下文放在栈中,栈中的先进后出,就像往一个罐子中放东西,拿出来的时候,先拿出的是罐子顶部的东西,也就是后放进去的东西,那么首先进栈的全局上下文是在栈底,最先进入,但是最后出来;函数上下文在函数被调用时产生,放入栈中,执行完后退出来;而全局上下文在程序退出前出栈

上下文在其所有代码都执行完毕后被销毁

上下文的生命周期:

1》创建阶段

这个阶段会创建变量对象、确定this指向,变量作用域链等

2》执行阶段

完成变量的赋值,执行其他js代码等

3》销毁阶段

执行上下文出栈,对应的引用失去内存空间,等待回收

作用域链

上下文创建的时候会创建变量对象arguments,并确定变量对象的作用域链

每个执行上下文对应一个作用域;所以我们有全局作用域和函数作用域,对应全局上下文和函数的上下文

函数中首先会在自己的变量对象中查找,没找到会沿着作用域链往上查找,但是他不会往下一级查找

      console.log(content); // hello
      function greet() {
        var content = "hi";
        console.log(content); // hi
        function response() {
          var str = "你好";
          console.log(content); //hi
        }
        response();
      }
      greet();

content greet(全局变量对象) ----- content response (greet函数变量对象))----- str(response函数变量对象)

response变量对象中没有找到,它就往greet变量对象中找,如果greet函数的变量对象中也没有,就从全局变量对象中找

es6增加了块级作用域的概念:由最近的一堆{}花括号界定;if块、while块、function块

变量

变量声明

var let const关键字都可以声明变量

比较三者

1》变量提升不同;var 存在变量提升,let没有;或者说他们的变量提升不同

      console.log(num); // undefined
      var num = 1;
      console.log(num); // ReferenceError: Cannot access 'num' before initialization
      let num = 1;

let 在声明前使用变量会报错,也就是我们说的暂时性死区

2》作用域不同;var 声明的变量作用域在最近的上下文中(全局或函数的上下文),而let是块级作用域

var定义的age实在全局作用域中

      if (true) {
        var age = 20;
      }
      console.log(age);  // 20

if形成了块级作用域,全局作用中域访问不到就报错了

      if (true) {
        let age = 20;
      }
      console.log(age);  // ncaught ReferenceError: age is not defined

3》声明同名变量不同;var 可以在同一作用域下声明同名变量,而let不行,会报错

      var str = "hihi";
      var str = "嗨嗨";
      console.log(str); //嗨嗨
      let str = "hihi";
      let str = "嗨嗨"; // Uncaught SyntaxError: Identifier 'str' has already been declared
      console.log(str); // 嗨嗨

4》在全局上下文中声明变量,var声明的变量会添加到window对象中(如果没有使用var来声明,直接赋值也会添加到window对象上,不会报错),而let声明的变量不会被添加到window对象中

      var num1 = 20;
      let num2 = 22;
      console.log(window.num1);  // 20
      console.log(window.num2);  // undefined

const和let差不多,唯一不同的时它声明的是个常量,声明时必须赋值,声明之后,就不能重新赋值(引用类型只要不改变引用地址就行)

变量提升

一个上下文创建的时候会创建变量对象,创建变量对象的过程:

1》建立argument对象,他是一个伪数组,属性名是:0,1,……,属性值就是传入的值

2》函数提升;在变量对象中创建一个变量名为函数名,值为指向函数内存地址的引用

3》变量提升;在变量对象中以变量名建立一个属性,属性值为undefined;但是let/const声明的变量没有赋值undefined,所以不能提前使用

      console.log(num);
      var num = 0;

相当于:

var num
console.log(num)
num=0

函数的提升先于变量的提升,首先函数的声明提升,然后变量提升

如果 var 变量与函数同名,则在这个阶段,以函数值为准,在下一个阶段,函数值会被变量值覆盖

      console.log(cal); // cal函数
      var cal = 10;
      function cal(num1, num2) {
        return num1 - num2;
      }
      console.log(cal); // 10

相当于:

     function cal() {
        return num1 - num2;
      };
      var cal;
      console.log(cal);
      cal = 10;
      console.log(cal);

内存

基本数据类型存在栈中,引用类型存在堆中

栈中存数据想罐子中放东西,先放的放在底下,取出的时候,最后才拿出来;栈中先进后出

堆数据结构是树状结构,从堆中拿数据就像从书架中找书

垃圾回收:基本思路就是确定变量不会再使用,就释放它的内存,这个过程是周期性的,隔一段时间回收一次

一般是函数的上下文执行完毕,函数上下文退出函数调用栈,解除变量引用,内存释放,等待垃圾回收;全局的上下文是再退出的时候才被销毁,所以我们尽量减少全局变量,也要尽量减少闭包

  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2022-05-05 11:09:15  更:2022-05-05 11:10:14 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 22:44:53-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码