对象
语言发展简史
机器语言 -> 汇编语言 -> 低级语言(面向过程)->高级语言(面向对象) -> 模块系统 -> 框架 -> 系统接口(API)
es5和es6的对象
在es6中的面相对象与es5中的面向对象的区别是极大的,ea6中的面相对象则更像java,c++等,而且在es5中的class保留字,在es6中也成了实际有效的关键字。
面向对象特点
- 抽象:把核心的东西抽出来,把与我们要解决的问题有关的东西拿出来摆在面前
- 封装:让使用对象的人不考虑内部实现,只考虑功能使用把内部的代码保护起来,只留出一些个api接口供用户使用
- 继承:就是为了代码的复用,从父类上继承出一些方法和属性,子类也有自己的一些属性
- 多态:实际上是不同对象作用与同一操作产生不同的效果。多态的思想实际上是把“想做什么”和“谁去做“分开
对象的组成 - 方法—函数:过程、动态的
- 属性—变量:状态、静态的
es5的对象
- 对象的创建
在ECMAScripts5以及更早的版本当中对象只是简单的键值对合集
//以函数的形式来写对象,没有专门的声明类
function Person(name, age){
this.name=name;
this.age=age;
}
//即是构造函数,又是类
- 对象的方法
//添加方法
Person.prototype.showName=function (){
alert(this.name);
};
//方法独立于类之外
- 方法的继承
//没有专门的继承方法
function Worker(name, age, job){
Person.call(this, name, age);
this.job=job;
}
Worker.prototype=new Person();
//没有专门继承父类方法的方法
Worker.prototype.constructor=Worker;
es6的对象
提供了四个新的关键字
class
类声明
constructor
构造函数
extends
继承
super
父类/超类
- 类的创建
//有单独的类声明、构造函数声明
class Person{
constructor(name, age){
//相当于对象的构造函数
this.name=name;
this.age=age;
}
}
- 类的方法
class Person{
//类是类,构造函数是构造函数
constructor(name, age){
this.name=name;
this.age=age;
}
showName(){
alert(this.name);
}
//方法写在类里,相当于在对象的原型上编程
showAge(){
alert(this.age);
}
}
- 方法的继承
class Worker extends Person{
//有专门的继承方法
constructor(name, age, job){
super(name, age);
this.job=job;
}
showJob(){
alert(this.job);
}
}
方法的继承
原型是JavaScript继承的基础,在早期版本当中,JavaScript严重限制了原型的使用。
原型链
正常情况下,无论是通过构造函数还是Object.create()
方法创建对象,其原型是在对象被创建时指定的。对象原型在实例化之后保持不变,直到ES5都是JavaScript编程最重要的设定之一,虽然在ES5中添加了Object.getPrototypeof()
方法来返回任意指定对象的原型,但仍缺少对象在实例化后改变原型的标准方法。所以,在ES6中添加了Object.setPrototypeof()
方法来改变这一现状,通过这个方法可以改变任意指定对象的原型,它接受两个参数:被改变原型的对象及替代第一个参数原型的对象。
let teacher = {
introduce() {
return 'i am a teacher'
}
}
let student = {
introduce() {
return 'i am a student'
}
}
//以teacher为原型
let myTeacher = Object.create(teacher);
console.log(myTeacher.introduce());
//i am a teacher
console.log(Object.is(Object.getPrototypeOf(myTeacher), teacher))
//true
//改变原型
Object.setPrototypeOf(myTeacher, student);
console.log(myTeacher.introduce());
//i am a student
console.log(Object.is(Object.getPrototypeOf(myTeacher), student))
//true
ES6新增方法super
let onPerson = {
introduce() {
return "i'm a person and" + super.introduce();
// return `i'm a person and ${Object.getPrototypeOf(this).introduce.call(this)}`
//同意
}
}
Object.setPrototypeOf(onPerson, student);
console.log(onPerson.introduce());
//i'm a person and i am a student
console.log(Object.is(Object.getPrototypeOf(onPerson), student))
//true
super在多重继承中非常有用
let onePerson = {
introduce() {
return `i'm a person and ${Object.getPrototypeOf(this).introduce.call(this)}`
}
}
Object.setPrototypeOf(onePerson, student);
let anoPerson = Object.create(onePerson);
console.log(student.introduce())
//i am a student
console.log(onePerson.introduce())
//i'm a person and i am a student
console.log(anoPerson.introduce())
//Uncaught RangeError: Maximum call stack size exceeded
//i'm a person and i am a student
super 引用不是动态变化的,它总是指向正确的原型