ES6学习笔记(一)class类

2018-12-04  本文已影响0人  大大大大大西瓜G

一:ES5中的仿类

JS在ES5及更早版本中都不存在类,与类最接近的是:创建一个构造器,然后将方法指派到该构造器的原型上。这种方式通常被称为创建一个自定义类型,例如:
function PersonType(name) {
        this.name = name ;
}
PersonType.prototype.sayName = function() {
  console.log(this.name);
}
let person = new PersonType('张三');
person.sayName();      //   输出  '张三'
console.log(person instanceof PersonType);      //   true
console.log(person instanceof Object);              //    true

//   此代码中 PersonType 是一个构造函数,并创建了单个属性name。
//   sayName() 方法被指派到原型上,因此在 PersonType 对象的所有实例上都共享了此方法
//   接下来使用 new 运算符创建了 PersonType 的一个新实例 person ,此对象会被认为是一个通过原型继承了 PersonType 与 Object 的实例

二:ES6中class类的基本用法

ES6引入了Class(类)这个概念,作为对象的模板,通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。【它看起来很想其它语言中的类】。上面的代码用ES6的“类”改写,就是下面这样。
class PersonClass {
      // 等价于 personType 构造器
      constructor(name) {
              this.name = name;
      }
     //  等价于 personType .prototype.sayName 
      sayName() {
              console.log(this.name)
      }
}
let person = new PersonClass('李四');
person.sayName();        //    输出  '李四'

console.log(person instanceof PersonClass);    //    true
console.log(person instanceof Object);       //     true
console.log(typeof PersonClass);             //      'function'
console.log(typeof PersonClass.prototype.sayName);      //     'function'
这个PersonClass类声明的行为非常类似上例中的PersonType,类声明允许你在其中使用特殊的 constructor 方法名称直接定义一个构造器,而不需要线定义一个函数再把它当做构造器使用。由于类的方法使用了简写语法,于是就不再需要使用 “function” 关键字。

三:为何要使用类语法

尽管类与自定义类型之间有相似性,但仍然要记住一些重要的区别:
1. 类声明不会被提升,这与函数定义不同,类生命的行为与let相似,因此程序在执行到达圣明厨之前,类会存在于暂时性死区内;
2. 类声明中的所有代码会自动运行在严格模式下,并且无法退出严格模式;
3. 类的所有方法都是不可枚举的,这是对于自定义类型的显著变化,后者必须用Object.defineProperty()才能将方法改变为不可枚举;
4.类的所有方法内部都没有 [[constructor]] ,因此使用 new 来调用它们会抛出错误;
5.调用类构造器时不适用 new 关键字,会抛出错误;
6.试图在类的方法内部重写类名,会抛出错误;

因此,上例中的PersonClass声明实际上就直接等价于以下未使用类语法的代码

//    直接等价于  PersonClass  
let PersonType2 = (function() {
        "use strict" ;
        const PersonType2 = function(name) {
                //   确认函数被调用时使用了   new
                if (typeof new.target === "undefined") {
                        throw new Error('constructor 构造器必须要使用new 关键字调用!')
                }
                this.name = name;
        }
        Object.defineProperty(PersonType2.prototype,'sayName',{
                value: function() {
                        //   确认函数被调用时没有使用  new
                          if (typeof new.target !== "undefined") {
                                  throw new Error('方法不能被 new 调用')
                          }
                          console.log(this,name);
                },
                enumerable : false,
                writable : true,
                configurable : true
        });
        retuen PersonType2;
}())
代码讲解:
首先要注意这里有两个PersonType2声明:一个在外部作用域的let声明,一个在内部的const声明,这就是为何类的方法不能对类名称进行重写、而类外部的代码则被允许。构造函数检查了 new.target,以保证被调用时使用了 new ,否则就抛出错误。接下来,say.Name()方法被定义为不可枚举。并且此方法也检查了 new.target ,它则要保证在被调用时没有 new 。最后一步是将构造函数返回出去。

尽管不适用新语法也能实现类的任何特性。但类语法显著简化了所有功能的代码!

QQ图片20181112170456.jpg
上一篇下一篇

猜你喜欢

热点阅读