ES6中箭头函数,var,class详解

一,箭头函数和普通函数的区别

箭头函数简介:箭头函数相当于匿名函数,并且简化了函数定义。箭头函数有两种格式第一种,省略{}和rerurn。第二种可以包含多条语句,这时候就不能省略{ ... }和return,如果参数不是一个,就需要用括号()括起来:

//第一种
 x => x * x
//第二种
x => {
    if (x > 0) {
        return x * x;
    }
    else {
        return - x * x;
    }
}

等同于

//第一种
function (x){
return x*x
}
//第二种
function (x){
    if(x)>0{
        return  x*x
        }
      else{
        return  -x*x
        }
}

区别:

1、首先箭头函数作为匿名函数,是不能作为构造函数的,不能使用new
2、this,普通函数构造函数的 this 指向了一个新的对象;如果函数是作为对象的方法被调用的,则其 this 指向了那个调用它的对象;但是箭头函数的则会捕获其所在上下文的 this 值,作为自己的 this 值。在使用call或apply绑定时,相当于只是传入了参数,对this没有影响
3、箭头函数不绑定arguments,取而代之用rest参数…解决
4、箭头函数当方法使用的时候没有定义this绑定
var obj = {
  i: 10,
  a: () => console.log(this.i, this),
  b: function() {
    console.log( this.i, this)
  }
}
obj.a(); //undefined, Window
obj.b(); // 10, Object {...}
5、箭头函数不能当做Generator函数,不能使用yield关键字
6、不能简单返回对象字面量
7、箭头函数不能换行

二.用户上传图片,图片存储的地址

图片保存在服务器上,数据库存储的是图片的链接地址,数据库是不会真的把一个文件存进去的 他只是把这个文件存储的地址保存起来

三.let,var 的区别

1.var的作用于是函数作用于,而let是块级别(大括号括起来的内容),for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。

for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc

2.不存在变量提升,let所声明的变量一定要在声明后使用,否则报错。

// var 的情况
console.log(lemon); // undefined
var lemon= 1;

// let 的情况
console.log(zoey); // 报错
let zoey= 1;

3.暂时性死区

es6中规定,区域块中存在let和const命令,这个区块对这些命令声明的变量,最开始就是一个封闭的作用域,在申明之前就使用这些变量就报错,在let命令声明变量之前使用该变量都是不可以的。

var a = 1;
if(2>1){
    a = 3,//报错
    let a 
}

还有一些暂时性死区隐藏得比较深比如下面代码

//第一种
function sum(x=y,y=1){
    return [x,y]
}
sum()//报错,因为x=y时,y还没有赋值
//但是这样就没毛病
function sum(x=1,y=x){
    return [x,y]
}
sum()//[1,1]

//第二种
var x = x//不报错
    console.log(x);//undefined

let x = x;//报错:x is not defined

4.不允许重复声明

 // 报错
    function fn() {
        let a = 1;
        let a = 2;//Identifier 'a' has already been declared
    }
    fn()

 // 报错
    function fn1() {
        let a = 1;
        var a = 2;//Identifier 'a' has already been declared
    }
    fn1()

function fn2(arg) {
  let arg; // 报错
}

function fn3(arg) {
  {
    let arg; // 不报错
  }
}

5.let实际上为 JavaScript 新增了块级作用域

  • ES6 允许块级作用域的任意嵌套,内层作用域可以定义外层作用域的同名变量。
  • ES6 引入了块级作用域,明确允许在块级作用域之中声明函数。
  • ES6 规定,块级作用域之中,函数声明语句的行为类似于let,在块级作用域之外不可引用。

四.利用generator完成fibnaqi数列

1.什么是generator

Generator 函数是协程在 ES6 的实现,最大特点就是可以交出函数的执行权(即暂停执行)。

整个 Generator 函数就是一个封装的异步任务,或者说是异步任务的容器。异步操作需要暂停的地方,都用yield语句注明。

在 ES6 中定义一个生成器函数很简单,在 function 后跟上「*」即可:
function* foo1() { };
function *foo2() { };
function * foo3() { };

foo1.toString(); // "function* foo1() { }"
foo2.toString(); // "function* foo2() { }"
foo3.toString(); // "function* foo3() { }"
foo1.constructor; // function GeneratorFunction() { [native code] }

调用生成器函数会产生一个生成器(generator)。生成器拥有的最重要的方法是 next(),用来迭代:

function* foo() { };
var bar = foo();
bar.next(); // Object {value: undefined, done: true}

上面第 2 行的语句看上去是函数调用,但这时候函数代码并没有执行;一直要等到第 3 行调用 next 方法才会执行。next 方法返回一个拥有 value 和 done 两个字段的对象。

生成器函数通常和 yield 关键字同时使用。函数执行到每个 yield 时都会中断并返回 yield 的右值(通过 next 方法返回对象中的 value 字段)。下次调用 next,函数会从 yield 的下一个语句继续执行。等到整个函数执行完,next 方法返回的 done 字段会变成 true。下面看一个简单的例子:

function* list() {
    for(var i = 0; i < arguments.length; i++) {
        yield arguments[i];
    }
    return "done.";
}

var o = list(1, 2, 3);
o.next(); // Object {value: 1, done: false}
o.next(); // Object {value: 2, done: false}
o.next(); // Object {value: 3, done: false}
o.next(); // Object {value: "done.", done: true}
o.next(); // Error: Generator has already finished

每次调用 next 方法,都会得到当前 yield 的值。函数执行完之后,再调用 next 方法会产生异常。

 function* gen(x) {
        var y = yield x + 2;
        return y;
    }

    var g = gen(1);
    console.log(g.next()); // { value: 3, done: false }
    console.log(g.next()); // { value: undefined, done: true }
上面代码中,调用 Generator 函数,会返回一个内部指针(即遍历器)g。这是 Generator 函数不同于普通函数的另一个地方,即执行它不会返回结果,返回的是指针对象。调用指针g的next方法,会移动内部指针(即执行异步任务的第一段),指向第一个遇到的yield语句,上例是执行到x + 2为止。

换言之,next方法的作用是分阶段执行Generator函数。每次调用next方法,会返回一个对象,表示当前阶段的信息(value属性和done属性)。value属性是yield语句后面表达式的值,表示当前阶段的值;done属性是一个布尔值,表示 Generator 函数是否执行完毕,即是否还有下一个阶段。

2.用generater完成fibnaqi数列

function* fab(max) {
    var count = 0, last = 0, current = 1;

    while(max > count++) {
        yield current;
        var tmp = current;
        current += last;
        last = tmp;
    }
}

var o = fab(10), ret, result = [];

while(!(ret = o.next()).done) {
    result.push(ret.value);
}

console.log(result); // [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]

ES6 也规定了类似的语法「for ... of」用来迭代

function fab(max) {
    var count = 0, last = 0, current = 1;

    while(count++ < max) {
        yield current;
        var tmp = current;
        current += last;
        last = tmp;
    }
}

for(var i of fab(10)) {
    console.log(i);
}

五.ES6 中class

1.定义

ES6提出了类(Class)的概念,让对象的原型的写法更像面向对象语言写法。 ES6中通过class定义对象,默认具有constructor方法和自定义方法。ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已.
  • 类的数据类型就是函数,类本身就指向构造函数。使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。
  • 类和模块的内部,默认就是严格模式

2.基本语法

function Point (x,y){
            this.x=x;
        this.y=y;
        }
        Point.prototype.toString= function(){
            return this.x+this.y;
        }

注意:constructor方法对应ES5的构造函数;创建类的方法不需要使用function关键字,方法之间不需要逗号分隔。

ES5中定义对象时组合使用构造函数模式和原型模式,构造函数模式用于定义实例属性,原型模式用于定义共享方法和共享属性,节省内存,而且支持向构造函数传递参数。

        function Point (x,y){
            this.x=x;
        this.y=y;
        }
        Point.prototype.toString= function(){
            return this.x+this.y;
        }

构造函数的原型(prototype)属性在ES6中依旧存在,这一点和ES5一样:类的方法都定义在类的原型(prototype)上,在类的实例上面调用方法,其实就是调用原型上的方法。

    //实例的constructor方法就是类的原型(prototype)的constructor方法
    class B{
      constructor(){}
    }
    let b = new B();
    console.log(b.constructor === B.prototype.constructor);//true   

3.ES6 Class的继承

Class通过extends关键字实现继承

class ColorPoint extends Point{}

子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工。如果不调用super方法,子类就得不到this对象。

    class ColorPoint extends Point {
      constructor(x, y, color) {
        super(x, y); // 调用父类的constructor(x, y)
        this.color = color;
      }
      toString() {
        return this.color + ' ' + super.toString(); // super代表父类原型,调用父类的toString()
      }
    }

上面代码中,constructor方法和toString方法之中,都出现了super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。

super这个关键字,既可以当作函数使用,也可以当作对象使用。第一种情况,super作为函数调用时,代表父类的构造函数,只能用在子类的构造函数中。ES6 要求,子类的构造函数必须执行一次super函数。第二种情况,super作为对象时,指代父类的原型对象。

如果子类没有定义constructor方法,这个方法会被默认添加。在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

        class Point {
          constructor(x, y) {
            this.x = x;
            this.y = y;
          }
        }
        
        class ColorPoint extends Point {
          constructor(x, y, color) {
            this.color = color; // ReferenceError
            super(x, y);
            this.color = color; // 正确
          }
        }

六.egg框架学习

转载于:https://my.oschina.net/u/3305487/blog/1525043

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值