es6再次解读(一)

117 阅读5分钟

常用的es6列举

let, const, promise, class类, 箭头函数, 字符串模板, 模块化, 扩展运算符, Array.from, flat等

let const

  1. 注意作用域死区
  2. const虽是常量,但是当他的值是引用类型的时候是可以间接修改的
const a= [1,2];
a.splice(1,1,100);
console.log(a);//[1, 100]

promise

就是一个对象,用来传递异步操作的消息。有三种状态:pending(进行中),resolved(已完成)和rejected(失败),有了promise对象,就可以将异步操作以同步操作的流程表示出来,避免了层层嵌套的回调函数

  1. 用来包装异步函数,使异步函数ajax,setTimeout等变成同步的写法,更人性化 详见:juejin.cn/post/684490…

从原型链到class

原型链

传统的javascript中只有对象,没有类的概念。它是基于原型的面向对象语言。原型对象特点就是将自身的属性共享给新对象。 如果要生成一个对象实例,需要先定义一个构造函数,然后通过new操作符来完成。构造函数示例: 详见: juejin.cn/post/684490…

//函数名和实例化构造名相同且大写(非强制,但这么写有助于区分构造函数和普通函数)
function Person(name,age) {
    this.name = name;
    this.age=age;
};
Person.prototype.say = function(){
    return this.name+","+this.age;
};
//通过构造函数创建对象,必须使用new 运算符
var obj=new Person("andy",100);

console.log(obj.say());//andy,100

构造函数生成实例的过程:

1.当使用了构造函数,并且new 构造函数(),后台会隐式执行new Object()创建对象; 2.将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。原型链指向构造函数的原型链。 3.执行构造函数的代码。 4.返回新对象(后台直接返回);

class

ES6引入了Class(类)这个概念,通过class关键字可以定义类。该关键字的出现使得其在对象写法上更加清晰,更像是一种面向对象的语言。如果将之前的代码改为ES6的写法就会是这个样子

// 定义一个名字为Person的类
class Person{
    //构造方法,用来接收参数
    constructor(name,age){
        //this代表的是实例对象
        this.name = name;
        this.age = age;
    }
    // 实例的方法,不要加上function
    say(){
        return this.name+","+this.age;
    }
}

var obj = new Person('andy',100);
console.log(obj,obj.say());//{name: "andy", age: 100}  "andy,100"

obj这个对象上除了继承构造函数里的属性,就只有一个__proto__的属性,指向构造函数的prototype。

小提示

  • class中的方法不用加function
  • class中的方法就相当于构造函数原型上的方法
  • class类也有prototype。他只是模拟了原型链继承
  • Person类也可以通过prototype属性对类添加方法

可以通过Object.assign方法来为对象动态增加方法

Object.assign(Person.prototype,{
    getName:function(){
        return this.name;
    },
    getAge:function(){
        return this.age;
    }
})
var obj=new Person("amy",120);
console.log(obj.getName()); // "amy"
console.log(obj.getAge()); // 120

constructor方法在new时会自动调用

相当于new 一个构造函数中的

obj.call(constructor,Array.from(arguments).slice(1))

constructor方法是类的构造函数的默认方法,通过new命令生成对象实例时,自动调用该方法。

class Car{
	constructor(name){
		console.log(name)
	}

}
var car1 = new Car('benz');// 'benz'

constructor方法如果没有显式定义,会隐式生成一个constructor方法。所以即使你没有添加构造函数,构造函数也是存在的。constructor方法默认返回实例对象this

constructor的实例属性与原型属性

constructor中定义的属性可以称为实例属性(即定义在this对象上),constructor外声明的属性都是定义在原型上的,可以称为原型属性(即定义在class上)。hasOwnProperty()函数用于判断属性是否是实例属性。其结果是一个布尔值, true说明是实例属性,false说明不是实例属性。in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

class不存在变量提升

所以需要先定义再使用。因为ES6不会把类的声明提升到代码头部,但是ES5就不一样,ES5存在变量提升,可以先使用,然后再定义。

class中的extend与super

class 可以 extends 自另一个 class。这是一个不错的语法,技术上基于原型继承。

class Person{
    //构造方法,用来接收参数
    constructor(name,age){
        //this代表的是实例对象
        this.name = name;
        this.age = age;
    }
    // 实例的方法,不要加上function
    say(){
		console.log('say')
        return this.name+","+this.age;
    }
}

class ItPerson extends Person{
	constructor(name){
	    // console.log(this.name)//这里不允许使用this
		super(name);//调用父类的构造函数《super指父类构造函数》
		//上方的参数必须要传,在react中可以不传。react.component类处理了
		console.log(this.name)
	}
	makeStrong(){
		console.log('strong')
	}
	writeJs(){
		console.log("通过this调用自己的方法",this.makeStrong());
		super.say()//此处的super相当于  父类.prototype
    }
}
var obj =new ItPerson("royal",200)
obj.writeJs();
// royal
// strong
// 通过this调用自己的方法 undefined
// say

class的调用方式

  • 通过new来调用
  • 直接调用
直接调用
class A {
  constructor() {
    this.x = 1;
  }
  static a() {
    console.log(111);
  }
}
A.a();//111

class 小结

  • 通过实例的__proto__可以给构造函数添加原型方法,影响范围是所有实例,不建议这么做
  • super功能很强大:
  1. super作为函数,super()代表的就是父类构造函数,里面的this就是类的实例。
  2. super作为对象,在普通的方法中super.的语法指向的是父类的原型对象,
  3. 在静态方法中使用super.语法的话就去父类的静态方法中找就行了。

super 指父类的构造函数 重点在于,在你调用父类构造函数之前,你无法在构造函数中使用 this。JavaScript 不会允许你这么做。

在react中,伴随着 class fields proposal 的发布,这个问题也就不复存在了。即便不显式调用构造函数,所有参数也会自动传入。这就允许像 state = {} 这样的表达式在必要时可以直接引用 this.props. 。在 Hooks 中,我们甚至都没有 super 或 this