原来我们写面向对象编程,都是在通过构造函数,然后在原型上写的,比如:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
Person.prototype.getName = function () {
return this.name;
}
Person.prototype.getAge = function () {
return this.age;
}
function Person (name, age) {
this.name = name;
this.age = age;
}
let person = new Person ('ReSword', 21);
console.log(person.getName(), person.getAge());
</script>
</html>
当然我们也可以通过Object.assign方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
// Person.prototype.getName = function () {
// return this.name;
// }
// Person.prototype.getAge = function () {
// return this.age;
// }
Object.assign(Person.prototype, {
getName () {
return this.name;
},
getAge () {
return this.age;
}
});
function Person (name, age) {
this.name = name;
this.age = age;
}
let person = new Person ('ReSword', 21);
console.log(person.getName(), person.getAge());
</script>
</html>
这样也是可以的
接下里介绍ES6中新增的class方法
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) { //构造方法(函数),调用new,自动执行
console.log(name, age);
}
}
let person = new Person('ReSword', 21);
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) { //构造方法(函数),调用new,自动执行
this.name = name;
this.age = age;
}
getName () {
return this.name;
}
getAge () {
return this.age;
}
}
console.log(typeof(Person));
let person = new Person('ReSword', 21);
console.log(person.getName(), person.getAge());
</script>
</html>
上面的Person使用的函数声明的方式,也可以是使用函数变量的方式来使用calss
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
const Person = class {
constructor (name, age) { //构造方法(函数),调用new,自动执行
this.name = name;
this.age = age;
}
getName () {
return this.name;
}
getAge () {
return this.age;
}
}
console.log(typeof(Person));
let person = new Person('ReSword', 21);
console.log(person.getName(), person.getAge());
</script>
</html>
这种方式也是可以的
--------------------------------------------------------------------------------------------
下面说明class中的方法名可以使用变量来代替
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
let AAA = 'BBB';
const Person = class {
constructor (name, age) { //构造方法(函数),调用new,自动执行
this.name = name;
this.age = age;
}
getName () {
return this.name;
}
getAge () {
return this.age;
}
AAA () {
return 'AAA-function';
}
}
let person = new Person('ReSword', 21);
console.log(person.AAA());
</script>
</html>
这样子我们去访问AAA 是有这函数的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
let AAA = 'BBB';
const Person = class {
constructor (name, age) { //构造方法(函数),调用new,自动执行
this.name = name;
this.age = age;
}
getName () {
return this.name;
}
getAge () {
return this.age;
}
[AAA]() {
return 'AAA-function';
}
}
let person = new Person('ReSword', 21);
console.log(person.BBB());
</script>
</html>
在我们加了 [] 之后,再去看
他会提示你AAA不是一个函数
我们去Person.prototype中查看
所以我们改成BBB
在我们改成BBB之后,
就可以运行到函数了
这其实就是JS的基础,我们知道后缀点和方括号都可以调用属性,但是后缀点是不能跟变量的,但是方括号可以
--------------------------------------------------------------------------------------------
还有就是class没有预解析,即下面这种写法是错误的
-------------------------------------------------------------------------------------
下面说明class中this指向的问题
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
getName () {
console.log('this: ', this);
return this.name;
}
}
let person = new Person ('ReSword', 21);
let {getName} = person;
console.log(getName());
</script>
</html>
这里是因为你将Person中方法提取了出来,那么这里的this就会指向运行环境,所以造成运行失败
解决方法1:
调用bind方法,将getName绑定到对象上
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
this.getName = this.getName.bind(this);
}
getName () {
console.log('this: ', this);
return this.name;
}
}
let person = new Person ('ReSword', 21);
let {getName} = person;
console.log(getName());
</script>
</html>
解决方法2:
使用箭头函数
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
this.getName = () => {
console.log('this: ', this);
return this.name;
}
}
}
let person = new Person ('ReSword', 21);
let {getName} = person;
console.log(getName());
</script>
</html>
------------------------------------------------------------------------------------------------
class里面还新增了两个函数getter和setter
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
get work () {
return 'gettter'
}
set work (value) {
console.log('setter: ' + value);
}
}
let person = new Person ('ReSword', 21);
person.work = 'student';//调用set
console.log(person.work);//调用get
</script>
</html>
get和set一般用于封装底层框架
-------------------------------------------------------------------------------------------------
class里的静态方法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, age) {
this.name = name;
this.age = age;
}
static fun () {
return 'this is a static function';
}
}
console.log(Person.fun());
</script>
</html>
----------------------------------------------------------------------------------------------
class里面的继承
我们先来看原JS的继承方法(即原型链)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
Person.prototype.getName = function () {
return this.name;
}
function Person (name, work) {
this.name = name;
this.work = work;
}
Student.prototype = new Person ();//继承方法
function Student (name, work, grade) {
Person.call(this, name, work);//继承属性
this.grade = grade;
}
let student = new Student ('ReSword', 'Student', 'Junior');
console.log(student.work);
console.log(student.getName());
</script>
</html>
再来看class通过extends关键字的继承
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, work) {
this.name = name;
this.work = work;
}
getName () {
return this.name;
}
}
class Student extends Person {
constructor (name, work, grade) {
super(name, work);
this.grade = grade;
}
}
let student = new Student('ReSword', 'Student', 'Junior');
console.log(student.work);
console.log(student.getName());
</script>
</html>
注意点:
1,
等同于
2,必须要在super之后才能使用this,这是因为子类的创建是基于父类的,只有super方法才能调用父类实例
3,父类的静态方法也会被子类所继承
上面只是父类的属性调用,下面是讲父类的方法调用:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title></title>
<link rel="stylesheet" href="">
</head>
<body>
</body>
<script>
class Person {
constructor (name, work) {
this.name = name;
this.work = work;
}
getName () {
return `This is father's function ${this.name}`;
}
}
class Student extends Person {
constructor (name, work, grade) {
super(name, work);
this.grade = grade;
}
getName () {
console.log(super.getName());
return `This is son's function ${this.name}`;
}
}
let student = new Student('ReSword', 'Student', 'Junior');
console.log(student.work);
console.log(student.getName());
</script>
</html>
注意点:
如果直接在子类中写和父类相同名字函数,那么其实际上只会执行子类的函数,
如果想要执行父类的函数,请使用super