美文网首页
8. es6 class 类,

8. es6 class 类,

作者: wudimingwo | 来源:发表于2018-12-08 10:00 被阅读0次
      function Animal (name, age) {
        this.name = name;
        this.age = age;
      }

构造函数的缺点

  • 不看函数体, 无法知道是普通函数还是构造函数
  • 构造函数当做普通函数执行, 会产生全局变量.

es6 class

      class Animal {

      }
      console.log(typeof Animal);/ function


babel翻译

"use strict";
      / 可以看出 这个函数的作用,就是为了让构造函数只能用 new 的方式进行调用
      function _classCallCheck(instance, Constructor) {
        if(!(instance instanceof Constructor)) {
          throw new TypeError("Cannot call a class as a function");
        }
      }

      var Animal = function Animal() {
        _classCallCheck(this, Animal);
      };
  • 只能通过 new 进行调用
      Animal();/ 报错
      new Animal();/ 不报错
  • 在同一个块级作用域下,不允许重复声明
  • 先定义后使用, 也就是有暂时性死区(TDZ)

constructor

            class Animal {
/注意在这里定义函数 不能出现 function (){} 只能用es6声明函数的方法
                constructor(name, age = 18){
                  this.name = name;
                  this.age = age;
                }
            }

              console.log(Animal.prototype.constructor == Animal);/ true
  • 可知 class {} 这个大括号不是 对象, 是一种语法糖
  • 语义化很好, 类名, 构造函数 两个概念分了开来.
  • 疑问? 在 这个类里定义的函数, 是在这个类的 原型上定义嘛?
    是的

为什么用原型?

  • 增加代码复用性
  • 节省空间
            class Animal {
                constructor(name, age = 18){
                  this.name = name;
                  this.age = age;
                }
/ 相当于定义在原型上.
                showName () {
                  console.log(this.name);
                }
            }
              
              let dog = new Animal('dog',2);
              console.log(dog.showName == Animal.prototype.showName);/true

可知, 在class{ } 里定义的函数, 就是定义在原型上的.

什么是静态属性,静态方法? 就像 jq里的工具方法
对应的是 实例方法, 原型链上的方法.
例子 Object.is()

            class Animal {
                constructor(name, age = 18){
                  this.name = name;
                  this.age = age;
                }
                showName () {
                  console.log(this.name);
                }
                / 相当于 Animal.createInstance 在Animal 函数上进行定义
                static createInstance (name,age) {
                  return new Animal(name,age)
                }
                static a = 123/ 报错
            }
              
              let dog = Animal.createInstance('dog',2);
              console.log(dog);
              

可知, static 方式只能在 Animal 上定义方法, 暂不能定义属性


一等公民 class function

  • 可以当做参数
  • 可以被返回
  • 可以立即执行
  • 可以赋值给其他变量

当参数

              function create (fn) {
                return new fn();
              }
              
              let obj = create(class{
                constructor (){
                  this.name = 'mike'
                }
              });
              console.log(obj);

立即执行

              let obj = new class {
                constructor (name ){
                  this.name = name;
                }
                
              }('mike');
              
              console.log(obj);

被返回

              function returnClass () {
                let count = 0;
                return class{
                  constructor (name) {
                    this.name = name;
                    this.count = count;
                  }
                }
              }
              
              let obj = new (returnClass())('mike')/ 正常
/这里可以看出 默认会先 执行 new returnClass, 再对返回函数进行()执行
              let obj = new returnClass()('mike')/ 报错
              console.log(obj);

class 生成器方法

              class iteratorArray {
                constructor (arr = []) {
                  this.arr = arr;
                }
                
                *[Symbol.iterator](){
                  yield *this.arr[Symbol.iterator]()
                }
              }
              
              let arr = new iteratorArray([1,2,3]);
              
              for(let item of arr) {
                console.log(item);
              }
image.png

上面的代码到底干了什么?
一个类返回的对象可以通过 设置 *Symbol.iterator{yield} , 进行迭代
yield *this.arrSymbol.iterator 的意思是把arr的指针添加进实例对象的指针组之中.

测试 可以 yield * this.arr, 因为默认会调用arr的迭代器[Symbol.iterator]

              class iteratorArray {
                constructor (arr = []) {
                  this.arr = arr;
                }
                
                *[Symbol.iterator](){
                  yield *this.arr
                }
              }
              
              let arr = new iteratorArray([1,2,3]);
              
              for(let item of arr) {
                console.log(item);
              }
image.png

测试: 我们可以任意的添加各种指针

              class iteratorArray {
                constructor (arr = [],arr1 = []) {
                  this.arr = arr;
                  this.arr1 = arr1;
                }
                
                *[Symbol.iterator](){
                  yield *this.arr;
                  yield *this.arr1;
                  yield *[7,8,9];
                  yield 10
                }
              }
              
              let arr = new iteratorArray([1,2,3],[4,5,6]);
              
              for(let item of arr) {
                console.log(item);
              }
image.png

测试是否可以用next


image.png

继承,
增加代码复用
类,本身的概念里就包好,要把相似共同的部分抽象出来

es5继承

          function Father (name,age) {
            this.name = name;
            this.age = age;
          }
          Father.prototype.showName = function () {
            console.log(this.name);
          }
          
          function Son () {
            Father.call(this);
          }
          严格来讲, 实际上是有几种继承方式的
          这几种方式,都会继承但不会让父级实例化,
          或者说, 这几种算是 无new继承
          Son.prototype = Object.create(Father.prototype);
          Son.prototype.__proto__ = Father.prototype;
          Object.setPrototypeOf(Son.prototype,Father.prototype);       
          
          当然最经典的继承 应该是 new 实例化
          圣杯继承
            function temp () {}
            temp.prototype = Father.prototype;
            Son.prototype = new temp();
   

es6继承

          class Animal {
            constructor (name = 'mike', age) {
              console.log(name);
              this.name = name;
              this.age = age;
            }
            showName(){
              console.log(this.name);
            }
          }
          子类,派生类
          class Person extends Animal {
            constructor(name){
              super(name)
        /相当于 Animal.call(this,name)
        / 或者应该这么理解?
            /this = new Animal() / 返回一个this?

            }
            show () {
              console.log(super.showName = Animal.prototype.showName);/true
              console.log(super == Animal.prototype);/ 报错, 
            }

          }
            let p = new Person();

注意, 子类使用extends 继承父类时, constructor里一定要有super字段
否则报错.
不许把super() 放在 this.赋值语句的前面,否则报错.
super 作为对象的时候, 指向的是父类的原型 Father.prototype,
但this自动指向实例
super 必须执行,或者调用属性, 否则报错?

好奇,babel怎么翻译的

'use strict';

// 这是用来在 原型上或者构造函数上定义函数用的.
var _createClass = function() {
        function defineProperties(target, props) {
          for(var i = 0; i < props.length; i++) {
            var descriptor = props[i];
            descriptor.enumerable = descriptor.enumerable || false;
            descriptor.configurable = true;
            if("value" in descriptor) descriptor.writable = true;
            Object.defineProperty(target, descriptor.key, descriptor);
          }
        }
        return function(Constructor, protoProps, staticProps) {
          if(protoProps) defineProperties(Constructor.prototype, protoProps);
          if(staticProps) defineProperties(Constructor, staticProps);
          return Constructor;
        };
      }();

// 返回最终的实例, 要跟下面调用的语句一起看
      function _possibleConstructorReturn(self, call) {
        if(!self) {
// 这一句确实不太懂, 如果new 了个构造函数, 有可能会让this 是 undefined嘛? 
// 下面报错信息翻译 大概是说, super 没有被调用, 初始化失败?
          throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
        }
        return call && (typeof call === "object" || typeof call === "function") ? call : self;
      }

// 用来继承的
      function _inherits(subClass, superClass) {
确保 传入的是个函数
        if(typeof superClass !== "function" && superClass !== null) {
          throw new TypeError("Super expression must either be null or a function, not " + typeof superClass);
        }

生成目标构造函数的原型,并继承 父级构造函数的原型,
并且让目标原型的构造函数指向目标构造函数.
我这说的肯定不是人话.
        subClass.prototype = Object.create(superClass && superClass.prototype, {
          constructor: {
            value: subClass,
            enumerable: false,
            writable: true,
            configurable: true
          }
        });

这一句非常,相当的让人意外,
此前考虑过继承的时候,从来没有考虑这个东西,
这一句的意思是, 让目标构造函数继承 父级构造函数.
这是把函数当成了对象.
我有点明白了, 因为函数上有可能定义一些函数和属性,
单纯只是原型上的继承,无法继承这一类的函数和属性.
真是周密啊周密.
        if(superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass;
      }

// 这是用来 保证 用 new
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

var Animal = function () {
  function Animal() {
    var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'mike';
    var age = arguments[1];

    _classCallCheck(this, Animal);

    console.log(name);
    this.name = name;
    this.age = age;
  }

  _createClass(Animal, [{
    key: 'showName',
    value: function showName() {
      console.log(this.name);
    }
  }]);

  return Animal;
}();

var Person = function (_Animal) {
让原型和函数各自继承
  _inherits(Person, _Animal);

  function Person(name) {
保证用new 的方式调用
    _classCallCheck(this, Person);

    return _possibleConstructorReturn(this, (Person.__proto__ || Object.getPrototypeOf(Person)).call(this, name));
  }

  return Person;
}(Animal);

var p = new Person();

好奇害死猫, 陌生字段有点多, 回头再看吧...

相关文章

  • 8. es6 class 类,

    构造函数的缺点不看函数体, 无法知道是普通函数还是构造函数构造函数当做普通函数执行, 会产生全局变量. es6 c...

  • ES6 class与继承

    class是什么 class是定义类的方法。ES6之前用构造函数的方式定义类,ES6引入了class。 class...

  • 深入理解JS面向对象 - JavaScript实现继承的五种方式

    一、类与实例 1. 类的声明 传统function类的声明 ES6中的class声明 1.1 ES6 class与...

  • 2JavaScript设计模式--class/extends

    ES6语法 类 class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板...

  • react组件

    es6 的class类的继承 运用es6 class继承 通过继承React.Component类来定义一个组件

  • 第三十二节: ES6 Class类

    1. ES6 Class 类 ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板...

  • 第三十二节: ES6 Class类

    1. ES6 Class 类 ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板...

  • 深入理解ES6中class的this指向

    在ES6中,引入了类似其他语言的类的写法:即class(类),作为类对象模板。ES6 的class可以看作一个语法...

  • ES6 class类

    在ES6以前,没有类的概念,所有的面向对象都是基于原型实现的。ES6中可以通过class定义类,但是class的本...

  • ES6 class类

    ES6 class类知识点梳理 大概从几个方面来讲解ES6 class类和传统的构造函数的区别。 必须要有cons...

网友评论

      本文标题:8. es6 class 类,

      本文链接:https://www.haomeiwen.com/subject/uyoxhqtx.html