ES6中class类特性与JavaScript的构造函数之间的区别

什么是类:
在ES6中新增加了类的概念,可以使用class关键字声明一个类,
之后以这个类来实例化对象。类抽象了对象的公共部分,它泛指
某一大类( class )对象特指某一个,通过类实例化一个具体的对象
表面看起来可以支持正式的面向对象编程,但实际上它背后使用的仍然
原型和构造函数的概念
同时class类是构造函数的【语法糖

一、类定义

 	  //1. 匿名类
      let Example = class {};
      //2.命名类
      let Example = class Example {};
      //3.类声明
      class Example {}
      //不可以重复声明一样的名字,如果同时声明一个的类名会报错

二、类不会被提身,他不具备变量提升

	  class Example {}
      let wq = new Example();
      //在声明一个类时,必须是先声明一个类,再去实例这个类对象
      //不能是先实例这个类对象,再去声明这个类,他不具备提升作用
	  //跟构造函数作比较
      let star = new Star();
      function Star() {}
      //构造函数具备变量提升,其实是function函数具备变量提升,构造函数可以先实例对象,在声明构造函数

三、创建类和添加方法

	  class Sxample {
      constructor(uname, age) {
          this.uname = uname;
          this.age = age;
      }
        show(money) {
          console.log(this.uname + money);
      }
        artistic(talent) {
          console.log(this.uname + talent);
         }
      }
      var example1 = new Sxample("王总", 18);
      var example2 = new Sxample("王老板", 28);
      console.log(example1.uname, example1.age);
      console.log(example2.uname, example2.age);
      example1.show("很有钱");
      example2.artistic("很有钱");
	
	 /*
       知识要点:
         1.类constructor构造函数:
              constructor()方法是类的构造函数(默认方法),用于传递参数返回实例对象,
              通过new命令生成对象实例时,自动调用该方法。如果没有显示定义,类内部会自动给拽们创建一个constructor
		 2.总结要点
             (1) 通过class 关键字创建类,类名我们还是习惯性定义首字母大写
             (2) 类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象
             (3) constructor函数只要new生成实例时,就会自动调用这个函数,如果我们不写这个函数,类也会自动生成这个函数
             (4) 生成实例 new 不能省略(这个new干了些啥)
                     1.在内存中创建了一个新对象
                     2.这个新对象内部的[[Prototype]]指针被赋值为构造函数的prototype属性
                     3.构造函数内部的this被赋值为了这个新对象(即this指向新对象)
                     4.执行构造函数内部的代码(给新对象添加属性)
                     5.如果构造函数返回非空对象,则返回该对象:否则,返回刚创建的新对象
            (5) 最后注意语法规范,创建类,类名后面不要加小括号,生成实例类名后面加小括号,构造函数不需要加function
            (6) 我们类里面所有的函数不需要写function
            (7) 多个函数方法之间不需要添加逗号分隔
      */

四、(extends、super)类的继承

	//1.extends
    class Father {
          constructor() {}
          money() {
          		console.log(10000 + "元");
      	  }
     }
     class Son extends Father {
     	   /*money() {
           		console.log('我自己有100块钱');
           }*/
           money1() {
           		console.log(100 + "元");
           }
      }
      var son = new Son();
      son.money();
      son.money1();
	   /*
			知识要点:
			  // 继承中的属性或者方法查找原则:就近原则
        	  // 1.继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
        	  // 2.继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就进原则)
	   */
	//2.super调用父类的构造函数----------------------------------------------------------
      class Father {
        constructor(x, y) {
          this.x = x;
          this.y = y;
        }
        sum() {
          console.log(this.x + this.y);
        }
      }
      class Son extends Father {
        constructor(x, y) {
          super(x, y);
          this.x = x;
          this.y = y;
        }
      }
      var son = new Son(1, 2);
      son.sum();
    //3.super调用父类的普通函数----------------------------------------------------------
      class Father {
        constructor(uname) {
          this.uname = uname;
        }
        say() {
          return "我是爸爸";
        }
      }
      class Son extends Father {
        constructor(uname) {
          super(uname);
        }
        say() {
          console.log("我是儿子");
          console.log(super.say() + "的儿子" + this.uname);
        }
      }
      var son = new Son("张三");
      son.say();
      /*
		  知识要点:
		  	 (1).super关键字用于访问和调用对象父类上的函数。可以调用父类的构造函数,也可以调用父类的普通函数	
		  	 (2)使用super时要注意几个问题(*代表比较常用的注意事项)
                  1.super()只能在子类构造函数和静态方法内使用
                  2.不能单独引用super()关键字,要么用它调用构造函数,要么用它引用静态方法  *
                  3.调用super()会调用父类构造函数,并将返回实例赋值给this  *
                  4.super()的行为如同调用构造函数,如果需要给父类构造函数传参,则需要手动传入
                  5.如果没有定义类构造函数,在实例化派生类时会调用super(),而且会传入所有传给子类的参数
                  6.在类构造函数中,不能调用super()之前引用this  *
                  7.如果在子类中显示定义了构造函数,则要么必须在在其中调用super(),要么必须在其中返回一个对象
	  
	  */

五、子类继承父类方法同时扩展自己的方法

	// 父类有加法方法
      class Father {
        constructor(x, y) {
          this.x = x;
          this.y = y;
        }
        sum() {
          console.log(this.x + this.y); //8
        }
      }
      // 子类继承父类加法方法 同时 扩展减法方法
      class Son extends Father {
        constructor(x, y) {
          // 利用 super 调用父类的构造函数
          // super 必须在子类this之前调用 但也可以省略掉this的操作
          super(x, y);
          //this.x = x;
          //this.y = y;
        }
        subtract() {
          console.log(this.x - this.y); //2
        }
      }
      var son = new Son(5, 3);
      son.sum();
      son.subtract();

六、类遵循严格模式
什么是严格模式:
JavaScript除了提供正常模式外,还提供了严格模式。ES5的严格模式是采用具有限制性
JavaScript变体的一种方式,即在严格的条件下运行的JS代码
严格模式在IE10以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略
怎么开启严格模式:
【为函数开启严格模式】两种情况
一、为脚本开启严格模式
为整个脚本文件开启严格模式,需要在所有语句之前放一个特定语句 “use strict”;(或 ‘use strict’)
二、为函数开启严格模式
要给某个函数开启严格模式,需要把 “use strict”;(或 ‘use strict’;)声明放在函数体所有语句之前

	//1.没有开启严格模式时,里面的this指向是window
	function fn() {
        console.log(this); //window
      }
      fn();
    //2.当开启严格模式时,里面的this指向是undefined
	function fn() {
        "use strict";
        console.log(this); //undefined
      }
      fn();
    //3.而class类默认是在严格模式下
     class Star {
        show() {
          function uname() {
            console.log(this);//undefined
          }
          uname();
        }
      }
      var star = new Star();
      star.show();

七、类的静态属性

	//1.构造函数里的静态成员和实例成员
      function Star(uname, age) {
        this.uname = uname;
        this.age = age;
        // this.show = function () {
        //   console.log("我是实例成员");
        // };
      }
      var star = new Star("王总", 18);
      console.log(star.uname);
      console.log(Star.uname); //实例成员不可以通过构造函数来访问
      // star.show();
      Star.sex = "男";
      console.log(star.sex); //静态成员不可以通过对象来访问
      console.log(Star.sex);
      Star.prototype.show = function () { //通过prototype来添加方法知识优化了在里面添加方法,但实际他还是要通过实例对象来访问这个函数法法
        console.log("我是通过原型的方法");
      };
      star.show(); //通过实例来访问
      star.__proto__.show = function () { 
        console.log("我是方法");
      };
      star.show(); //通过实例来访问
      console.log(star);
      /*
           知识要点:
               构造函数的静态成员和实例成员
               	 (1)静态成员:在构造函数本上添加的成员称为静态成员,只能由构造函数本身访问
               			1.静态成员 在构造函数本身上添加成员
               			2.静态成员 只能通过构造函数来访问
               	 (2)实例成员:在构造函数内部创建对象成员称为实例成员,只能由实例化的对象来访问
               			1.实例成员就是构造函数内部通过this添加的成员 uname、age、sing 就是实例成员
               			2.实例成员只能通过实例化的对象来访问
     */
	//2.类里面的静态
      class Star {
        constructor(uname, age) {
          this.uname = uname;
          this.age = age;
        }
        show() {
          console.log("我原型对象是" + this.uname);
        }
        static sing(uname) {
          console.log("我原型对象是" + uname);
        }
      }
      var star = new Star("王总", 18);
      var star1 = new Star("王老板");
      star.show();
      Star.sing("王老板");
      //3.子类的静态方法能够通过super来调用父类的静态方法
      class Person {
        static getName() {
          return "lear";
        }
      }
      class Student extends Person {
        static getName2() {
          return super.getName() + ",hi";
        }
      }
      console.log(Student.getName2());
      /*
		类里面的静态属性——[static]
          1.class本身的属性,即直接定义在类内部的属性(Class.propname),
          不需要实例化。 ES6 中规定,Class 内部只有静态方法,没有静态属性。
          2.静态方法通常用于执行不特定于实例的操作,也不要求存在类的实例于
          原型成员类似,静态成员每个类上只能有一个
          3.静态类成员在类定义中使用static关键字作为前缀,在静态成员中,
          this引用自身。其他所有约定跟原型成员一样。
	*/

八、把类当成一个特殊函数,类的是返回对象

	 // 1.通过typeof操作符检测类标识符,表明它是一个函数
      class Person {}
      console.log(Person);
      console.log(typeof Person); //function
	// 2.类标识有prototype属性,而这个原型也有一个constructor属性指向类自身
      class Person1 {}
      console.log(Person1.prototype); //{constructor: ƒ}
      console.log(Person1 === Person1.prototype.constructor); //true
	// 3.与普通函数一样,可以使用instanceof操作符检查构造函数原型是否存在于实例的原型链中
      class Person2 {}
      var p = new Person2();
      console.log(p instanceof Person2); //true
	 /*
        4.由此可知,可以使用instanceof操作符检查一个对象与构造函数,以确定这个对象是不是类
        的实例。只不过此时的构造函数要使用标识符,比如前面的例子中要检查p和Person2如前所述
        ,类本身具有与普通构函数一样的行为,在类的上下文中.类本身在使用new调用时就会被当成
        构造函数。重点在于,类中定义的 constructor 方法【不会】被当成构造函数,在对它使用		
        instanceof操作符时会返回false但是,如果在创建实例时直接将类构造函数当成普通构造函
        数来使用,那么instanceof操作符的返回值会返回ture
     */
	class Person3 {}
      var p3 = new Person3();
      console.log(p3.constructor === Person3); //true
      console.log(p3 instanceof Person3); //true
      console.log(p3 instanceof Person3.constructor);  /false
      var p4 = new Person3.constructor();
      console.log(p4.constructor === Person3); //false
      console.log(p4 instanceof Person3); //false
      console.log(p4 instanceof Person3.constructor); //true

九、实例化对象共享原型对象

	 // 1.构造函数共享
      function Person(uname, age) {
        this.uname = uname;
        this.age = age;
        this.sing = function () {
          console.log("我在里面创建");
        };
      }
      Person.prototype.show = function () {
        console.log("我是原型链");
      };
      var wz = new Person("王总", 18);
      var zh = new Person("张总", 28);
      wz.sing();
      zh.sing();
      wz.show();
      zh.show();
      console.log(wz.sing === zh.sing); //false
      console.log(wz.show === zh.show); //true
      console.log(star.__proto__ === star1.__proto__); //true




      // 2.类的共享
      class Example {
        constructor(a, b) {
          this.a = a;
          this.b = b;
        }
        sum() {
          return this.a + this.b;
        }
      }
      Example.prototype.sub = function () {
        console.log("我是原型对象");
      };
      let exam1 = new Example(2, 1);
      let exam2 = new Example(3, 1);
      console.log(exam1.sum === exam2.sum); //true
      console.log(exam1.sub === exam2.sub); //true
      // 类的所有实例共享一个原型对象。
      console.log(exam1.__proto__ === exam2.__proto__); //true

十、类是一个块级作用域

	 {
        function fn() {
          console.log("我可以被外面给获取到");
        }
        class Star {
          show() {
            console.log("我不能被我们给获取到");
          }
        }
      }
      fn();
      var star = new Star();  // ReferenceError: Star is not defined
      star.Star();

你可能感兴趣的:(1024程序员节,javascript,前端,es6)