JavaScript基础知识总结

这一篇博客,主要针对波老师的前端基础进阶前6篇的内容,结合自己看的一些书,对JavaScript中的内存空间、执行上下文、变量对象、作用域链、闭包、this的一个自我总结。如有意见,欢迎交流。

前端基础进阶

1.内存空间

内存的生命周期:分配内存,使用内存,释放内存
大致分为 栈、堆、队列(相应的数据结构,可以去看相关书籍)

JavaScript中采用的垃圾清理机制:标记清除
垃圾收集器会在运行的时候给存储在内存中的所有变量都加上标记,然后,它会去掉环境中的变量以及被环境中的变量应用的标记,在此之后再把加上标记的变量都将被视为准备删除的变量。最后,垃圾收集器完成内存的清除工作,销毁那些带标记的值并收回它们所占用的内存空间

JavaScript中5种基本数据类型:undefined、null、String、Number、Boolean,保存在栈内存中
引用类型:Array、Object,保存在堆内存中
基本数据类型的使用,是对值的复制,等于在栈内存中重新开辟一个内存空间
引用类型,是一个引用(指针)指向堆内存中的内存空间地址

2.执行上下文

执行上下文可以理解为函数执行的环境,每一个函数执行时(注意,是在执行时候),都会给对应的函数创建这样一个执行环境

JavaScript中运行环境大致分为三种:
1.全局环境:JavaScript代码运行起来会首先进入该环境
2.函数环境:当函数被调用执行时,会进入当前函数中执行代码
3.eval:(不建议使用,忽略)

因此在一个JavaScript程序中,必定会产生多个执行上下文,JavaScript引擎会以栈的方式来处理它们,这个栈,我们称其为函数调用栈(call stack)。栈底永远都是全局上下文,而栈顶就是当前正在执行的上下文。

执行上下文是在函数执行时创建,那么执行上下文的周期又是什么呢?

分为两个阶段:
创建阶段:
      在这个阶段中,执行上下文会分别

  1. 创建变量对象
  2. 建立作用域链
  3. 确定this的指向

代码执行阶段:
      创建完成之后,就会开始执行代码,这个时候,会完成

  1. 变量赋值
  2. 函数引用
  3. 执行其他代码

执行完成后,出栈,等待垃圾回收机制处理回收

总结:执行上下文概念

  • 单线程
  • 同步执行,只有栈顶的上下文处于执行中,其他上下文需要等待
  • 全局上下文只有唯一的一个,它在浏览器关闭时出栈
  • 函数的执行上下文的个数没有限制
  • 每次某个函数被调用,就会有个新的执行上下文为其创建,即使是调用的自身函数,也是如此。

3.变量对象(活动对象)

在创建变量对象时,首先创建arguments对象,再检查function函数声明,最后检查var(let、const)变量声明创建属性

function test() {
    console.log(a);
    console.log(foo());

    var a = 1;
    function foo() {
        return 2;
    }
}
//有调用,才会进入call-stack
test();



// 创建过程
//执行上下文
testEC = {
    // 变量对象
    VO: {},
    scopeChain: {}
}


// VO 为 Variable Object的缩写,即变量对象
VO = {
    arguments: {...},  //注:在浏览器的展示中,函数的参数可能并不是放在arguments对象中,这里为了方便理解,我做了这样的处理
    foo: <foo reference>  // 表示foo的地址引用
    a: undefined
}

作者:这波能反杀
链接:https://www.jianshu.com/p/330b1505e41d
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

未进入执行阶段之前,变量对象中的属性都不能访问!
但是进入执行阶段之后,变量对象转变为了活动对象,里面的属性都能被访问了,然后开始进行执行阶段的操作。

4.作用域链

什么是作用域?作用域,可以理解为一套规则,从功能的角度来看,作用域确定了哪些变量可以被函数访问以及确定了this的赋值;从性能的角度上看,作用域关系到标示符解析的性能

作用域链,就是由当前函数的变量对象及其父作用域的变量对象,形成的链式结构,只能由嵌套子作用域访问父作用域

在ES6出来之前,JavaScript中只有全局作用域与函数作用域,并没有块作用域。
块级作用域类似函数作用域。

5.闭包

闭包是指有权访问另一个函数a作用域中的变量的函数b(在chrome中,a来指代是闭包)

闭包是一种特殊的对象,通过闭包,我们可以在其他的执行上下文中,访问到函数的内部变量

6.this

this的指向,是在函数被调用的时候确定的也就是执行上下文被创建时确定的。

如果调用者函数,被某一个对象所拥有,那么该函数在调用时,内部的this指向该对象。如果函数独立调用,那么该函数内部的this,则指向undefined。但是在非严格模式中,当this指向undefined时,它会被自动指向全局对象。

通过call、apply可以显式的指定this

function fn(num1, num2) {
    console.log(this.a + num1 + num2);
}
var obj = {
    a: 20
}

fn.call(obj, 100, 10); // 130
fn.apply(obj, [20, 10]); // 50

作者:这波能反杀
链接:https://www.jianshu.com/p/d647aa6d1ae6
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

通过new操作符调用构造函数,会经历以下4个阶段。

  • 创建一个新的对象;
  • 将构造函数的this指向这个新对象;
  • 指向构造函数的代码,为这个对象添加属性,方法等;
  • 返回新对象。

因此,当new操作符调用构造函数时,this其实指向的是这个新创建的对象

// 定义父级的构造函数
var Person = function(name, age) {
    this.name = name;
    this.age  = age;
    this.gender = ['man', 'woman'];
}

// 定义子类的构造函数
var Student = function(name, age, high) {

    // use call
    Person.call(this, name, age);
    this.high = high;
}
Student.prototype.message = function() {
    console.log('name:'+this.name+', age:'+this.age+', high:'+this.high+', gender:'+this.gender[0]+';');
}

new Student('xiaom', 12, '150cm').message();

作者:这波能反杀
链接:https://www.jianshu.com/p/d647aa6d1ae6
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值