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