JavaScript简介

JavaScript一种动态类型、弱类型、基于原型的客户端脚本语言,用来给HTML网页增加动态功能。
JavaScript由三部分组成:
ECMAScript(核心)+DOM(文档对象模型)+BOM(浏览器对象模型)
ECMAScript作为核心,规定了语言的组成部分:语法、类型、语句、关键字、保留字、操作符、对象
DOM把整个页面映射为一个多层节点结果,开发人员可借助DOM提供的API,轻松地删除、添加、替换或修改任何节点。
BOM支持可以访问和操作浏览器窗口的浏览器对象模型,开发人员可以控制浏览器显示的页面以外的部分

一、声明变量

es6声明变量:

let x=1;//声明一个变量

const y=2;//声明一个只读常量,声明时必须赋值,之后值不可修改

es5声明变量:

var z=3;//声明一个变量

区别:

let不存在变量提升,而var存在

ps:变量提升:先解析代码,获取所有声明的变量,然后代码自上而下依次运行将变量提升到自身所在作用域的头部,这将导致脚本还未执行,而变量却存在,只不过变量的值为undefined。

var num=2;
function fun() {
  console.log(num);//undefined    
  if(false){
  	var num=3;
    console.log(num);//代码不执行 
  }  
}

从上面代码可以看出,即使if语句不执行,但是num却依然声明了。

ES5只有全局作用域和函数作用域,没有块集作用域。而let则实际上为JavaScript新增了块级作用域。

用它所声明的变量,只在let命令所在的代码块内有效。

场景一:

let name = 'zach'
while (true) {
    let name = 'obama'
    console.log(name)  //obama
    break
}
console.log(name)  //zach
var name = 'zach'
while (true) {
    var name = 'obama'
    console.log(name)  //obama
    break
}
console.log(name)  //obama

场景二:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 10

上面代码中,变量i是var声明的,在全局范围内都有效。所以每一次循环,新的i值都会覆盖旧值,导致最后输出的是最后一轮的i的值。

而使用let则不会出现这个问题。

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6](); // 6

场景三:

var clickBoxs = document.querySelectorAll('.clickBox')
for (var i = 0; i < clickBoxs.length; i++){
    clickBoxs[i].onclick = function(){
        console.log(i)
    }
}//i为全局变量,每次点击输出最后一次的i值

运用闭包解决:

function iteratorFactory(i){
    return function(){ 
       console.log(i)
    }
}
var clickBoxs = document.querySelectorAll('.clickBox');
for (var i = 0; i < clickBoxs.length; i++){
  clickBoxs[i].onclick = iteratorFactory(i)
}

二、作用域

作用域:ps:变量能够起作用的范围

在es5中只有全局作用域和函数作用域,而es6中新增了一个块级作用域

var arr="love";//全局作用域下的全局变量
function foo() {
 var arr="you";//函数作用域下的局部变量
}
foo();

块级作用域用 { } 包含

{
   let num=.....;//块级作用域写法
    ........
}

*.在某个作用域中用let声明局部变量时,该作用域会形成封闭作用域,即在变量声明之前,该变量不可使用,并且不允许在相同的作用域下重复声明同一个变量.

var tmp="234";
{
    tmp=345;//报错
    let tmp="567";//在声明变量之前不可使用,区域已封闭
}
let garde=88;
let grade=79;//报错
let num=110;
{
   let num=99;
   console.log(num);//99
}
console.log(num);//110

从上面的代码可以看出用let声明的变量绑定了自己所在的作用域,互不影响.

三、箭头函数

箭头函数解决的问题

简化了写法。箭头函数适用于函数体只有一行的情况;当有多行时,可用普通函数增加可读性。 少打代码,结构清晰
明确了this。传统JS的this是在运行的时候确定的,而不是在定义的时候确定的;而箭头函数的this是在定义时就确定的,不能被改变,也不能被call,apply,bind这些方法修改。明确运行时候this指向谁,不用运行时判断this指向。
注:箭头函数没有自己的this,他的this就是外层的this,指向上一个不是箭头函数的函数的this。因为js的机制,所以指向的是一个非箭头函数的函数的作用域。

箭头函数与普通函数的区别

普通function的声明在变量提升中是最高的,箭头函数没有函数提升
箭头函数没有this,函数体内部的this对象就是定义的时候所在的对象而不是使用时所在的对象
箭头函数没有arguments对象,该对象在函数体内不存在,如果要用,可以使用rest参数
箭头函数不能作为构造函数,不能被new,没有property
call和apply方法只有参数,没有作用域
不可以使用yield命令,因此箭头函数不能做Generator函数

四、类继承

ES5通过原型链实现继承:

function SuperType() {
        this.property = true;
    }
    SuperType.prototype.getSuperValue = function() {
      return this.property;
    };
    function SubType() {
        this.subproperty = false;
    }
    //继承了SuperType
    SubType.prototype = new SuperType();
    SubType.prototype.getSubValue = function() {
        return this.subproperty;
    };
    var instance = new SubType();
    alert(instance.getSuperValue()); //true

ES6引入了Class(类)这个概念,更像面向对象编程的语法。

class Animal {
    constructor(){
        this.type = 'animal'
    }
    says(say){
        console.log(this.type + ' says ' + say)
    }
}
let animal = new Animal()
animal.says('hello') //animal says hello
class Cat extends Animal {
    constructor(){
        super()
        this.type = 'cat'
    }
}
let cat = new Cat()
cat.says('hello') //cat says hello

上面代码首先用class定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。简单地说,constructor内定义的方法和属性是实例对象自己的,而constructor外定义的方法和属性则是所有实力对象可以共享的。
super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

五、设置默认函数参数

ES6中可以设置默认函数参数,如function A(x,y=9){};

六、promise

promise产生背景:解决回调地狱问题,处理异步请求

promise用法:链式调用,成功和失败的回调,三个状态,pending状态改变时触发。状态一旦改变就不会再变。

七、字符串模板 Template strings

var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

八、Iterators(迭代器)+ for…of

迭代器有个next方法,调用会返回:
(1).返回迭代对象的一个元素:{ done: false, value: elem }
(2).如果已到迭代对象的末端:{ done: true, value: retVal }

for (var n of ['a','b','c']) {
  console.log(n);
}