ES6的类Class基础知识点

原始生成实例对象的方法是通过构造函数:

function Person(name, age) {
  this.name = name;
  this.age = age
}
Person.prototype.sayName = function () {
  console.log(this.name);
}
var person = new Person(‘wang‘, 18);
person.sayName();

  

ES6引入了类的概念,通过class关键字用来定义类。

// es6
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name)
  }
}

  

说明:constructor() {} 为类的构造方法。而this代表实例对象。  constructor之外用来定义方法。注意:方法之间不需要用逗号或是分号分隔。

实际上,Person就是就是构造函数的语法糖:

console.log(typeof Person);  // function
console.log(Person === Person.prototype.constructor);  // true

  

注:所有类的自身属性,都定义在constructor里,在constructor之外定义的方法,都是在类的prototype上;

和es5的构造函数类的区别:

1. es5的prototype中的属性和方法是可枚举(enumerable)的:

console.log(Object.keys(Person.prototype)); // ["sayName", "name"]

  

es6的prototype中的属性和方法是不可枚举的(non-enumerable)的:

console.log(Object.keys(Person.prototype)); // []

  

2.es6的类的内部,默认使用严格模式,es5不是

3.es6必须使用new调用,否则会报错;es5可以直接用

4.es6不存在变量提升(let变量声明也不会提升),es5因为是普通的函数,所以存在变量提升

(hasOwnProperty可以用来判断类的属性是否在类自身还是类的原型上)

(由于__proto__并不是js本身拥有,而是浏览器单方面实现的私有属性,因此不建议在开发中使用,替代方法为:Object.getPrototypeOf(person),参数为实例对象,可以得到实例对象的类的原型:

console.log(Object.getPrototypeOf(person) === Person.prototype) // true

  

)

注:es6有提案,用来实现私有属性和方法(现有能用的方法是加下划线表示私有属性和方法,或者使用Symbol生成独特的仅供内部使用的属性和方法),即在属性或方法之前加#;

this指向问题:

es6类的方法内部如果含有this,则默认指向类的实例。但是,如果将类的方法提取出来用,this将会指向其运行的环境,而不是类的实例。解决方法就是绑定this(.bind(this))或是使用箭头函数;

例如:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name)
  }
}
var person = new Person(‘wang‘, 12);
person.say();
var { say } = person;
say();  // Uncaught TypeError: Cannot read property ‘name‘ of undefined

  

Class的取值(getter)和存值(setter):

与es5一样,在类的内部可以使用get,set关键字,对某个属性设置存值函数和取值函数,在相应操作中会执行get或set函数:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    // console.log(this.name)
  }
  get name() {
    console.log(‘get name‘);
  }
  set name(value) {
    console.log(‘set name = ‘ + value)
  }
}
var person = new Person(‘wang‘, 12);
person.name = ‘wangpei‘;  // set name = wangpei
person.name;  // get name

Class可以在内部使用Generator方法

在某个方法之前加上*,就表示该方法是一个Generator函数

Class的静态方法

说明:即只能通过类本身来调用,不能在实例化对象中调用。但是可以被子类继承,子类同样不能在实例中调用

注意:和私有方法(即只能在类内部调用,不能通过类本身调用,例如在类的内部定义var a = 1;这个变量a就只能在类内部调用,外部无法使用)的概念区别

注:在es5中,静态方法是直接定义在构造函数自身的方法:

Person.write = function(){}

  

es6中:需要通过static关键字定义,表示该方法不会被实例继承,但会被子类继承;

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    // console.log(this.name)
  }
  static write() {
    console.log(this.name);
  }
  get name() {
    console.log(‘get name‘);
  }
  set name(value) {
    console.log(‘set name = ‘ + value)
  }
}
var person = new Person(‘wang‘, 12);
Person.write();  // Person
person.write();  // Uncaught TypeError: person.write is not a function

  

注意:静态方法内部无法访问到类的实例对象的属性和方法。只能访问到类本身的属性和方法

注意:es6规定,Class的内部只有静态方法,没有静态属性,即类的内部不能通过static为属性定义值(static name: ‘wang‘)

Class的实例属性:

Class的实例属性也可以写在constructor方法外部,相当于在constructor内部写入this.xxx = xxx;

例:

class Person {
  sex=33;
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}
var person = new Person(‘wang‘, 12);
console.log(person.sex);  // 33

  

注:这个特性是es7的新提案。目前需babel转码器支持,浏览器暂不支持

 

构造函数(非Class)独有的命令:new.target

new.target 命令一般用于构造函数中,用于判断构造函数是怎么调用的;如果构造函数不是通过new调用的,会返回undefined,否则会返回构造函数:如果有子类继承父类,它总是返回子类构造函数;利用这个特性,可以写出不能独立使用,必须继承后才能使用的类(构造函数)

注:只能在构造函数内部使用,不能在构造函数原型上使用(undefined)

例如:

function Person(name, age) {
  console.log(new.target);  // Person函数本身
  this.name = name;
  this.age = age
}
Person.prototype.sayName = function () {
  console.log(new.target);
}
var person = new Person(‘wang‘, 18);
person.sayName();  // undefined

  

Class的继承

语法:

// es6
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name);
    // console.log(this.name)
  }
  static write() {
    console.log(this.write);
  }
}
var person = new Person(‘wang‘, 12);
person.say();
class Student extends Person {
}
var student = new Student(‘yao‘, 24);
student.say(); // yao
Student.write(); // write函数本身

  

注:子类的内部如无constructor,则默认会添加constructor()和super()函数;

如子类定义了constructor,则必须同时定义super()方法(否则报错),因为子类没有自己的this对象,而是靠父类继承的this对象,再对其进行加工。如果不调用super方法,子类就得不到this对象;

由此可以理解,super是用来返回父类的实例对象的,然后才能在父类的实例上进行加工,从而构建子类的实例。

因此,子类使用this时,必须在super()之后,此时子类才会拥有父类实例的this对象

例如:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name);
    // console.log(this.name)
  }
  static write() {
    console.log(this.write);
  }
}
var person = new Person(‘wang‘, 12);
person.say();
class Student extends Person {
  constructor() {
  }
}
var student = new Student(‘yao‘, 24);  // Uncaught ReferenceError: this is not defined

  

值得注意的是:

super()虽然返回的是父类的实例对象,但是子类中的this指向的仍是子类,而不是父类。super()相当于Person.prototype.constructor.call(this)

super也可以作为对象来使用:(作为函数使用时,只能在constructor()方法中使用)

在普通方法中,super指向父类的原型对象,在静态方法中,super指向父类

例如:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name);
    // console.log(this.name)
  }
  static write() {
    console.log(this.write);
  }
}
class Student extends Person {
  constructor() {
    super();
    this.class = 1
    console.log(super.say)
  }
  run() {
    console.log(super.say)
  }
}
var student = new Student(‘yao‘, 24);
student.run(); // function say(){...}

  

注:作为对象时,不能直接使用super对象,只能使用super上的属性或方法(否则报错:Uncaught SyntaxError: ‘super‘ keyword unexpected here);因为super指向的是父类的原型对象,因此可以取得父类的原型上的属性或方法,但不能取到父类实例的属性或是方法;

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name);
    // console.log(this.name)
  }
  static write() {
    console.log(this.write);
  }
}
class Student extends Person {
  constructor() {
    super();
    this.class = 1
  }
  run() {
    console.log(super.say);  // function say(){...}
    console.log(super);  // 报错
    console.log(super.name);  // undefined
  }
  static eat() {
    console.log(super.name);  // Person
  }
}
var student = new Student(‘yao‘, 24);
student.run();
Student.eat();

  

**注意:es6规定,super()虽然指向的是父类的原型或实例,但是this指向的却是子类,如下:

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
    console.log(this.name);
  }
}
class Student extends Person {
  constructor() {
    super();
    this.class = 1
    this.name = ‘dong‘
  }
  run() {
    console.log(super.say());  // dong
  }
}
var student = new Student(‘yao‘, 24);
student.run();

  

子类获取父类的方法:

Object.getPrototypeOf(subClass);  // 父类

 

类的prototype属性和__proto__属性

__proto__是指向父类的指针

(1)子类的__proto__,表示构造函数的继承,指向父类

(2)子类prototype属性的 __proto__属性,表示方法的继承,总是指向父类的prototype属性

(3)子类原型的原型,是父类的原型,即子类的__proto__属性的__proto__属性,指向父类实例的__proto__属性。

class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
  say() {
  }
}
class Student extends Person {
  constructor() {
    super();
  }
}
console.log(Student.__proto__ === Person);  // true
console.log(Student.prototype === Person);  // false
console.log(Student.prototype.__proto__ === Person.prototype);  // true

  

 

 

 

 

 

 

 

 

 

 

 

 

时间: 2024-11-03 03:35:01

ES6的类Class基础知识点的相关文章

黑马程序员——Java I/O流基础知识点(File类)

File工具 File类就是用俩将文件或者文件夹封装对象,弥补流对象的不足--流只能操作数据,不能操作文件夹的 封装的是路径!!! 构造方法演示 1.可以将已有的未出现的文件或者文件夹封装成对象. File f1=new File("c:\\abc\\a.txt"): File f2=new File("d:\\abc","ab.txt"打印,会打印路径.:目录分隔符,为了更好地跨平台File. File类常见功能 1,创建 createNewF

C# .Net基础知识点解答

C# .Net基础知识点解答 1. 什么是.NET?什么是CLI?什么是CLR?IL是什么?JIT是什么,它是如何工作的?GC是什么,简述一下GC的工作方式? 通俗的讲,.Net是微软开发应用程序的一个平台: CLI是Common Language Infrastructure,是公共语言架构: CLR是Common Language Runtime,即公共语言运行时: IL是.Net编译器产生的中间代码,称为通用中间语言CIL(Common Intermediate Language),CIL

js基础知识点总结

js基础知识点总结 如何在一个网站或者一个页面,去书写你的js代码:1.js的分层(功能):jquery(tool) 组件(ui) 应用(app),mvc(backboneJs)2.js的规划():避免全局变量和方法(命名空间,闭包,面向对象),模块化(seaJs,requireJs) 常用内部类:Data Array Math String HTML属性,CSS属性HTML:属性.HTML属性="值":CSS:对象.style.CSS属性="值"; class和f

Spring4.x 基础知识点

# Spring4.x 基础知识点## 第二章 快速入门- 一般情况下,需要在业务模块包下进一步按分层模块划分子包,如user\dao.user\service.viewspace\dao.viewspace\service等.对于由若干独立子系统组成的大型应用,在业务分层包前还需要加上子系统的前缀.包的规划对于大型应用非常重要,它直接关系到应用部署和分发的便利性.- 在配置文件的定义上,一般也是按模块进行划分,一定程度上降低争用.- 在拼接SQL语句的句前和句后都加一个空格,这样避免分行SQL

.NET基础知识点

.NET基础知识点   l  .Net平台  .Net FrameWork框架   l  .Net FrameWork框架提供了一个稳定的运行环境,:来保障我们.Net平台正常的运转   l  两种交互模式 C/S:要求客户的电脑上必须要安装一个客户端:qq.360.快播等..... B/S:要求客户的电脑上只需要安装一个浏览器   l  书写代码需要注意的地方: n  代码中出现的所有标点都是英文半角 shift键快速切换中文半角和英文半角 n  shift+空格切换全角/半角 n  在c#代

JavaScript 开发者经常忽略或误用的七个基础知识点

英文原文:7 JavaScript Basics Many Developers Aren't Using (Properly) JavaScript 本身可以算是一门简单的语言,但我们也不断用智慧和灵活的模式来改进它.昨天我们将这些模式应用到了 JavaScript 框架中,今天这些框架又驱动了我们的 Web 应用程序.很多新手开发者被各种强大的 JavaScript 框架吸引进来,但他们却忽略了框架身后浩如星海的 JavaScript 实用技巧.本文将为你呈献其中7个基础知识点. 1. 在

JAVA基础知识点总结(全集)

1.JAVA简介 1.1java体系结构:j2se,javaweb,j2ee 1.2java特点:平台无关(虚拟机),垃圾回收(使得java更加稳定) 1.3 JDK与JRE,JDK:java开发环境,JRE:java运行环境 1.4第一个java程序:HelloWorld,java的入口是main(public static void main(String[] args)) 1.5java程序的开发步骤:.java编译(javac)成.class运行(java).class文件 2.基本数据

Android中Binder的基础知识点

Android Binder基础知识点 一 传统IPC和Binder机制的比较 传统IPC: 1)收方无法获得对方进程可靠的UID/PID,从而无法鉴别对方身份. 2)接入点开放,无法建立私有通道. 3)socket, 管道和消息队列需要两次数据拷贝,传输效率差. 4)共享内存的方式控制复杂,难以使用. Binder机制: 1)为发送方添加UID/PID身份. 2)既支持实名Binder也支持匿名Binder. 3)传输过程只需要一次拷贝. 二 Binder中的面向对象思想 Binder对象是一

图解Python 【第五篇】:面向对象-类-初级基础篇

由于类的内容比较多,分为类-初级基础篇和类-进阶篇 类的内容总览图: 本节内容一览图: 今天只讲类的基础的面向对象的特性 前言总结介绍: 面向对象是一种编程方式,此编程方式的实现是基于对 类 和 对象 的使用 类 是一个模板,模板中包装了多个"函数"供使用(可以讲多函数中公用的变量封装到对象中) 对象,根据模板创建的实例(即:对象),实例用于调用被包装在类中的函数,对象是一个类的实例 实例(instance):一个对象的实例化实现. 标识(identity):每个对象的实例都需要一个可