es6简单介绍

let和const

原先声明变量的形式

var test = 5;  //全局变量
function a()
{
  var cc=3; //局部变量
  alert(test);
}
function b(){alert(test);}

test = 5;//全局变量 
function a()
{
  aa=3; //全局变量
  alert(test);
}

在es6之前,作用域只有全局作用域和函数作用域,没有块级作用域,所以考虑如下代码

{ var a = 6;
  var a = 8}
console.log(a)  // 答案是8

我们本来想着用{}表示一块作用域,外面应该访问不到里面的变量,但是事实是var声明的变量泄漏到全局作用域了。所以引出let
let有三个个特点:

  • 不能重复赋值
  • 作用域是局部作用域
  • 不存在变量提升
{let a=10;
 let a=11}
Uncaught SyntaxError: Identifier 'a' has already been declared
{let a = 10}
a
Uncaught ReferenceError: a is not defined
    at <anonymous>:1:1

作用域是块级作用域

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

因为var定义的是全局,所以在内存中只维护一块空间,每次+1的时候这块空间的值发生改变,而数组中的每个函数的引用都指向这一块空间,当最后调用的时候那块空间的值就是10了,所以结果就是10了

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

let声明的是块级作用域,所以每一次循环的i其实都是一个新的变量,每次循环都会创建新的内存空间,每个放到数组中的函数都指向对应的内存空间的值,等调用的时候就调用指向的值。那么问题来了,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算

变量提升

console.log(foo); // undefined
var foo = 2;

在es6之前,变量使用在定义之前得到的结果是undefiend,这种现象叫做变量提升,这其实不符合正常的编程逻辑。
js引擎在解释的时候从上到下,先找定义的变量,也就是说下面代码其实是这样的

var foo;
console.log(foo); // undefined
foo = 2;

有了let之后

console.log(foo); // 报错
let foo = 2;   

块级作用域

内层变量可能会覆盖外层变量

var tmp = 5;

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined

至于结果为啥是undefined参考变量提升的解释。在内部定义的var tmp = 'hello world';的在解释的时候在函数作用域内是先var tmp

用来计数的循环变量泄露为全局变量

for (var i = 0; i < 5; i++) {
  console.log(s[i]);
}

console.log(i); // 5

变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

const

const定义的变量有两点需要注意:

  • 不能只用来声明,声明的时候就必须赋值
  • 不能修改

const的作用域与let命令相同:只在声明所在的块级作用域内有效。

模板字符串

在es6之前,我们拼接字符串都有+,这种方式是繁琐的,可以使用反引号(`)标识。
反引号主要有3个作用:

  1. 当作普通字符串
  2. 定义多行字符串(相当于python的三引号)
  3. 在字符串中嵌入变量
d
10
`iloce${d}`
"iloce10"

箭头函数

箭头函数就是函数的一种缩写形式

//无形参
var f = () => 5;
// 等同于
var f = function () { return 5 };

//多个形参
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
  return num1 + num2;
};

箭头函数有一点需要注意
在es6之前,函数体内的this对象,就是使用时所在的对象,而不是定义时所在的对象

 var person = {
        name:'jack',
           age:18,  
        fav:function(){        
            console.log(this)
        }
    }

    person.fav();

用了箭头函数之后,函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象

 var person2 = {
    name:'jack',
    age:18,
    fav: ()=>{
         // 当前this指向了定义时person2对象时所处的对象(window)
         console.log(this);
      }
    }

 person2.fav();

为了解决这个问题, 使用对象的单体模式:

 var person2 = {
    name:'jack',
    age:18,
    fav() {
         // 当前this指向了定义时person2对象时所处的对象(window)
         console.log(this);
      }
    }

 person2.fav();

面向对象

在es6之前创建对象是这样做的

function Animal(name,age){
            this.name = name;
            this.age = age;

        }
        Animal.prototype.showName = function(){
            console.log(this.name);
            console.log(this.age);
        }

        var a = new Animal('小黄',5);
        a.showName();

我们在python中通过class就能定义一个对象,在es6中也可以这样做

class People {
	// 类似python中的init
	constructor(name,age){
		this.age = age;
		this.name = name;
	}
	eat(){console.log('111')}
	study() {console.log('1222')}
}

定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。

posted @ 2018-07-18 11:46  龙云飞谷  阅读(142)  评论(0编辑  收藏  举报