JavaScript - 琐碎摘录

147 阅读5分钟

JavaScript是什么

  • JavaScript是 动态类型、弱类型、基于原型 的 客户端脚本语言。

  • JavaScript由以下三部分组成:

  1. ECMAScript (核心):规定语言的组成部分:语法、类型、语句、关键字、保留字、操作符、对象等。ECMAScript是JavaScript语言的国际标准,JavaScript是ECMAScript的实现(即也可以有其他语言来实现ECMAScript标准)。
  2. DOM (文档对象模型 Document Object Model):HTML DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准。
  3. BOM (浏览器对象模型 Browser Object Model):允许JavaScript与浏览器对话(window对象)。

ECMA2015(ES6)

作用域

  • 在 ES6 之前,JavaScript 只有两种作用域: 全局变量 与 函数内的局部变量

    // 使用 var 关键字声明的变量不具备块级作用域的特性,它在 {} 外依然能被访问到。
    { 
        var x = 2; 
    }
    // 这里可以使用 x 变量
    
  • 在浏览器环境中, 全局作用域是针对 window 对象。

    • 使用 var 关键字声明的全局作用域变量属于 window 对象。即可以使用 window.xxx 访问变量。
    • 使用 let 关键字声明的全局作用域变量不属于 window 对象。
    • 在node中顶层对象指的是 global 对象。
  • 块级作用域

    • ES6 可以使用 let 关键字来实现块级作用域。let 声明的变量只在 let 命令所在的代码块  {}  内有效,在  {}  之外不能访问。
      { 
          let x = 2;
      }
      // 这里不能使用 x 变量
      
    • 块 (语法块)
      {}
      if(){}
      for(){}
      
  • 如何在ES5环境下实现let

    通过自执行函数来模拟块级作用域
    

变量

  • 为什么浏览器控制台分次用let或const声明,不报错?

  • 变量提升

    • 变量提升 只提升变量的声明,不提升赋值
      // eg1:
      var a = 1;
      var b = 2;
      // 实际为:
      var a,b;
      a = 1;
      b = 2;
      // eg2:
      var v='Hello World';
      (function(){
         alert(v);     // v is undefined
         var v='I love you';
      })()
      
    • 函数声明形式可以提升函数,函数表达式方式不能提升。
    • 函数提升优先于变量提升。
    • let不会变量提升,即变量必须在声明后使用,否则报错ReferenceError。
  • 暂时性死区

    • ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。即在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
    • 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
      if (true) {
        // TDZ开始
        tmp = 'abc'; // ReferenceError
        console.log(tmp); // ReferenceError
      
        let tmp; // TDZ结束
        console.log(tmp); // undefined
      
        tmp = 123;
        console.log(tmp); // 123
      }
      
    • [ES6]什么是变量提升和暂时性死区 - 简书 (jianshu.com)
  • let

    • let不允许在相同作用域中重复声明。
  • const

    • const声明的常量不能改变值,即声明时必须初始化。
      const a; // SyntaxError
      
    • const并非真正的常量。const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址不得改动。
      // 创建常量对象 
      const car = {type:"Fiat", model:"500", color:"white"}; 
      // 修改属性: 
      car.color = "red"; // √
      // 添加属性 
      car.owner = "Johnson"; // √
      
      //可以使用Object.freeze()方法来 冻结变量
      const obj = {
        name:"1024kb"
      }
      Object.freeze(obj)
      // 此时对象obj被冻结,返回被冻结的对象
      // 若对象的属性仍是引用类型,则对象的属性也需要被冻结才可
      
      // 实现Object.freeze()
      function myFreeze(obj){
          if(obj instanceof Object){
              Object.seal(obj); // 封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置
              let p;
              for (p in obj) {
                  if(obj.hasOwnProperty(p)){
                      Object.defineProperty(obj,p,{
                          writable: false
                      })
                  }
              }
          }
      
      }
      
    • 如何在ES5环境下实现const?
      使用Object.defineProperty()。这个API用于在一个对象上增加或修改属性。通过配置属性描述符,可以精确地控制属性行为。
      function _const(key,value){
          const desc = {
              value,
              writable:false
          }
          Object.defineProperty(window,key,desc)
      }
      _const('obj',{a:1})
      obj = {} // Cannot redefine property: obj
      

    。。。持续编辑中