zoukankan      html  css  js  c++  java
  • 浏览器学习笔记-07 js基础

    js 基础

    变量提升

    先通过下面这段代码,来看看什么是 JavaScript 中的声明和赋值。  

    var myname = '极客时间'
    

    这段代码你可以把它看成是两行代码组成的:

    var myname //声明部分
    myname = '极客时间' //赋值部分
    

    所谓的变量提升,是指在 JavaScript 代码执行过程中,JavaScript 引擎把变量的声明部分和函数的声明部分提升到代码开头的 “行为”。变量被提升后,会给变量设置默认值,这个默认值就是我们熟悉的 undefined。

    函数和变量在执行之前都提升到了代码开头。函数声明优先级高于变量声明,相同名称的声明,函数会覆盖变量声明,后面的函数声明会覆盖前面的函数声明。注意:不带var 关键字的是一个全局对象的属性,不是声明全局变量,建议使用 let const

    js 执行过程

    一段js代码 --> 编译阶段 --> 执行阶段

    • JavaScript 代码执行过程中,需要先做变量提升,而之所以需要实现变量提升,是因为 JavaScript 代码在执行之前需要先编译。
    • 在编译阶段,变量和函数会被存放到变量环境中,变量的默认值会被设置为 undefined;在代码执行阶段,JavaScript 引擎会从变量环境中去查找自定义的变量和函数。
    • 如果在编译阶段,存在两个相同的函数,那么最终存放在变量环境中的是最后定义的那个,这是因为后定义的会覆盖掉之前定义的

    栈溢出

    我们就来明确下,哪些情况下代码才算是“一段”代码,才会在执行之前就进行编译并创建执行上下文。一般说来,有这么三种情况

    • 当JavaScript执行全局代码的时候,会编译全局代码并创建全局执行上下文,而且在整个页面的生存周期内,全局执行上下文只有一份。
    • 当调用一个函数的时候,函数体内的代码会被编译,并创建函数执行上下文,一般情况下,函数执行结束之后,创建的函数执行上下文会被销毁。
    • 当使用eval函数的时候,eval的代码也会被编译,并创建执行上下文。

    每调用一个函数,JavaScript引擎会为其创建执行上下文,并把该执行上下文压入调用栈,然后JavaScript引擎开始执行函数代码。
    如果在一个函数A中调用了另外一个函数B,那么JavaScript引擎会为B函数创建执行上下文,并将B函数的执行上下文压入栈顶。
    当前函数执行完毕后,JavaScript引擎会将该函数的执行上下文弹出栈。
    当分配的调用栈空间被占满时,会引发“堆栈溢出”问题。

    var a = 2
    function add(b,c){
      return b+c
    }
    function addAll(b,c){
        var d = 10
        var result = add(b,c)
        return  a+result+d
    }
    addAll(3,6)
    

    1
    2
    3
    4
    5
    6

    let,const

    正是由于 JavaScript 存在变量提升这种特性,从而导致了很多与直觉不符的代码,这也是 JavaScript 的一个重要设计缺陷。

    作用域是指在程序中定义变量的区域,该位置决定了变量的生命周期。通俗地理解,作用域就是变量与函数的可访问范围,即作用域控制着变量和函数的可见性和生命周期。

    在 ES6 之前,ES 的作用域只有两种:全局作用域和函数作用域。

    ES6 引入了 let 和 const 关键字,从而使 JavaScript 也能像其他语言一样拥有了块级作用域。

    沿着词法环境的栈顶向下查询,如果在词法环境中的某个块中查找到了,就直接返回给 JavaScript 引擎,如果没有查找到,那么继续在变量环境中查找。

    作用链和闭包

    ES6 是如何通过变量环境和词法环境来同时支持变量提升和块级作用域,在最后我们也提到了如何通过词法环境和变量环境来查找变量,这其中就涉及到作用域链的概念。

    其实在每个执行上下文的变量环境中,都包含了一个外部引用,用来指向外部的执行上下文,我们把这个外部引用称为 outer。

    当一段代码使用了一个变量时,JavaScript 引擎首先会在 “当前的执行上下文” 中查找该变量。

    从图中可以看出,bar 函数和 foo 函数的 outer 都是指向全局上下文的,这也就意味着如果在 bar 函数或者 foo 函数中使用了外部变量,那么 JavaScript 引擎会去全局执行上下文中查找。我们把这个查找的链条就称为作用域链。
    在 JavaScript 执行过程中,其作用域链是由词法作用域决定的

    词法作用域

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

    词法作用域是代码阶段就决定好的,和函数是怎么调用的没有关系。词法作用域和函数声明的位置相关,和变量声明无关。

    块级作用域中的变量查找

    在编写代码的时候,如果你使用了一个在当前作用域中不存在的变量,这时 JavaScript 引擎就需要按照作用域链在上层作用域中查找该变量。

    闭包

    在 JavaScript 中,根据词法作用域的规则,内部函数总是可以访问其外部函数中声明的变量,当通过调用一个外部函数返回一个内部函数后,即使该外部函数已经执行结束了,但是内部函数引用外部函数的变量依然保存在内存中,我们就把这些变量的集合称为闭包。

    通常,如果引用闭包的函数是一个全局函数,那么闭包会一直存在直到页面关闭;但如果这个闭包以后不再使用的话,就会造成内存泄露。

    如果引用闭包的函数是个局部变量,等函数销毁后,在下次 JavaScript 引擎执行垃圾回收时,判断闭包这块内容如果已经不再被使用了,那么 JavaScript 引擎的垃圾回收器就会回收这块内存。

    所以在使用闭包的时候,你要尽量注意一个原则:如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大的话,那就尽量让它成为一个局部变量。

    this

    
    var bar = {
        myName:"time.geekbang.com",
        printName: function () {
            console.log(this.myName)
        }
    }
    function foo() {
        let myName = "极客时间"
        return bar.printName
    }
    let myName = "极客邦"
    let _printName = foo()
    _printName()
    bar.printName()
    

    作用域链和 this 是两套不同的系统,它们之间基本没太多联系

    执行上下文主要分为三种——全局执行上下文、函数执行上下文和 eval 执行上下文,所以对应的 this 也只有这三种——全局执行上下文中的 this、函数中的 this 和 eval 中的 this。

    1. 全局执行上下文中的 this
      window 对象,作用域链的最底端包含了 window 对象,全局执行上下文中的 this 也是指向 window 对象。

    2. 函数中的this

    • 在全局环境中调用一个函数,函数内部的 this 指向的是全局变量 window;
    • 通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身。
    1. eval 中的this
      只在被直接调用时,this指向才是当前作用域。
  • 相关阅读:
    把影响集中到一个点
    How to avoid Over-fitting using Regularization?
    适定性问题
    Numerical Differentiation 数值微分
    What Every Computer Scientist Should Know About Floating-Point Arithmetic
    Generally a good method to avoid this is to randomly shuffle the data prior to each epoch of training.
    What is the difference between iterations and epochs in Convolution neural networks?
    Every norm is a convex function
    Moore-Penrose Matrix Inverse 摩尔-彭若斯广义逆 埃尔米特矩阵 Hermitian matrix
    perl 类里的函数调用其他类的函数
  • 原文地址:https://www.cnblogs.com/SLchuck/p/13696807.html
Copyright © 2011-2022 走看看