js高级程序设计(一)

1. 一个完整的 JavaScript 实现应该由下列三个不同的部分组成:
  • 核心(ECMAScript)
  • 文档对象模型(DOM)
  • 浏览器对象模型(BOM)
    ECMAScript:JavaScript脚本语言的标准
    语法,类型,语句,关键字,保留字,操作符,对象
    DOM:为了解决编写一个html页面可以在任何浏览器上运行的问题
    针对XML但经过扩展用于HTML的应用程序接口
    BOM:提供很多对象,用于访问浏览器的功能
2. 数据类型:
  • 基本数据类型:Undefined、Null、Boolean、Number、 String
    复杂数据类型:Object
  • 鉴定给定变量的数据类型typeof:
    ES5:undefined boolean string number function object
    ES6:Symbol(创建后独一无二且不可变的数据类型 )
    https://juejin.im/post/5bdbb3406fb9a022752c319e#heading-7

eg:

typeof console.log ---> function
typeof null             ---> object
null instanceof Object---> false(历史bug,理解为空的对象引用)
var arr = [];
console.log(arr); ---> object
3.什么时候用==?什么时候用===

https://2ality.com/2011/12/strict-equality-exemptions.html#[3]
eg:尽量避免用==
obj.a == null 相当于obj.a === null || obj.a === undefined
obj.a == null 这种写法会给初级与高级开发者带来困惑,所以直接!obj.a

4. 变量提升
   a = 'a';
   var a;
   console.log( a );

事实上: var a 发生在编译阶段, a = 'a'发生在执行阶段. 然后 var a会被提升到当前作用域的最前面, a = 'a'留在原地等待执行阶段
经过编译后:

var a;  //被提升到当前作用域的最前面
a = 'a'; //留在原地,等待执行
console.log( a ); 

2.函数声明会被提升

show();
function show() {      
  console.log(a);
  var a = 'a';
}

编译后:

function show(){    
  var a;    //当前作用域的前面
  console.log( a );
  a = 'a';
}
show();

3.函数表达式不会被提升

show(); 
var show = function(){
 console.log( 'a' );
}

编译后:

var show;
show();  
show = function(){
  console.log( 'a' );  
}

4.当出现同名的函数与变量声明的时候, 函数声明会被优先提升,变量声明会被忽略

show(); 
var show;
function show() {
  console.log('你好');
}
show = function () {
  console.log('hello');
}

编译后:

function show() {
  console.log('你好');
}
show(); 
show = function () {
  console.log('hello');
}

5.如果有同名的函数声明,后面的会覆盖前面的
https://www.cnblogs.com/ghostwu/p/7287189.html

5.闭包

1>块级作用域(var let const)
var
使用此声明的变量会自动添加到最接近的环境
函数内部:最接近的环境是函数的局部环境
外层:全局环境,没有var声明,自动添加到全局环境
so,没有块级作用域

for( var i = 0; i < 5; i++ ) {
    console.log("循环");
}
console.log("依然访问到---"+i);

let

  • 存在块级作用域
  • 没有变量提升
for (let b = 0; b < 5; b++) {
  console.log(b);
}
console.log(b);
js-demo.js:36 Uncaught ReferenceError: b is not defined
    at js-demo.js:36
console.log(a);
let a="内容";

直接报错:

js-demo.js:40 Uncaught ReferenceError: Cannot access 'a' before initialization
    at js-demo.js:40

const
与let上述性质一致,区别:
1.一旦声明必须赋值,不能使用null占位。
2.声明后不能再修改
3.如果声明的是复合类型数据,可以修改其属性

const b="内容";
b="内容更改";

js-demo.js:34 Uncaught TypeError: Assignment to constant variable.
    at js-demo.js:34
const person={
  name:'my name'
}
person.name="my name update";

其他区别:
1>同一作用域下let和const不能声明同名变量,而var可以
2>let与const存在暂时性死区

var a = 100;
if(1){
    a = 10;
    console.log("判断前 a==" + a);
    let a= 1;
}
console.log("判断后 a==" + a);

Uncaught ReferenceError: Cannot access 'a' before initialization

大神忽略,作为小白的我,疑问如下:
1>let真的不存在变量提升?不存在的话,那怎么会报错呢?
2>js的编译与执行的原理是什么?

  • 问题1:首先理解变量的生命周期:
    1.声明阶段
    2.初始化阶段
    3.赋值阶段
    备注:通过声明阶段但是没有初始化,处于未定义阶段
    var
    var a;--->完成声明与初始化阶段
    a='content';--->赋值阶段
    函数
    function name() {}
    声明,初始化,赋值一步完成
    let
console.log(a);
let a;

声明被提前了,没有进行初始化,处于暂时性死区
https://juejin.im/post/5aa631ab5188255587233214

  • 问题2:
    js是一本脚本语言,可以不经过编译直接运行
    但也存在预编译的疑问,体现在变量或函数同名时
  • 预编译:变量与函数的提升
  • 执行阶段:
    https://juejin.im/post/59e85eebf265da430d571f89
    这篇文章讲述的已经十分详细
    总结:
    1>同步的主线程,异步的进入Event Table并注册函数
    2>指定的事情完成时,Event Table将函数移入Event Queue
    3>主线程执行完毕后,去Event Queue获取函数调用
    4>继续上面的过程,Event Loop

你可能感兴趣的:(js高级程序设计(一))