js面向对象
万事万物皆对象,面向对象的主要是把事物给对象化,包括其属性和行为(方法)。易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更加易于维护
封装
封装的过程就是把一些属性和方法放到对象中“包裹”起来,即如何创建对象。 假如我们将人(Preson)当作一个对象,它有一个属性(name),一个方法(sayName)
- 字面量方式创建对象
let personA = {
name:"张三",
sayName:function(){
console.log(this.name)
}
}
let personB = {
name:"李四",
sayName:function(){
console.log(this.name)
}
}
- 使用new Object()创建对象
let personA = new Object()
personA.name = "张三"
personA.sayName = function () {
console.log(this.name)
}
let personB = new Object()
personB.name = "李四"
personB.sayName = function () {
console.log(this.name)
}
这两种方式实例的对象存在缺点,一是需要实例多个对象时产生大量重复代码,二是创建的对象没有联系,不能反映出是同一个对象的实例
- 工厂模式创建对象
在介绍工厂模式前,先引入一个类的概念对象的抽象是类,类的具象化就是对象。比如:人就可以看作是一个类,而具体的某一个人就是一个对象,如张三就是一个对象。工厂模式就是把创建对象,添加属性方法,最终返回一个对象放到一个函数中,使用者只需要调用函数无需关注对象创建的细节
function createPerson(name) {
let person = new Object();
person.name = name;
person.sayName = function () {
console.log(this.name)
};
return person;
}
var personA = createPerson("张三")
var personB = createPerson("李四")
- 优点:工厂模式解决了字面量方式,new Object()方式大量重复代码问题
- 缺点:1.工厂模式模式没有解决对象识别问题得到的对象类型都是Object;
2.工厂模式下,类有新增的属性和方法每次都要生成一个新的类和新的对象
- 构造函数模式创建对象
构造函数与其他函数的区别就是构造函数需要new关键字来调用。通过new创建的实例一个经历了4步: 1.创建一个新对象; 2.将构造函数内的this绑定到新对象上; 3.给新对象添加属性和方法; 4.返回新对象
function Person(name) {
this.name = name;
this.sayName = function () {
console.log(this.name)
};
}
var personA = new Person("张三")
var personB = new Person("李四")
console.log(personA.constructor) //Person
console.log(personA.sayName==personB.sayName) //false
- 优点:通过构造函数创建的对象会有constructor属性,解决了对象识别问题
- 缺点:每个实例上的方法都会创建一次存储在不同内存中,浪费了内存
- 原型模式创建对象
在js中构造函数都存在prototype属性,指向原型对象,这个对象下的属性和方法都会被实例继承。实例对象中会有proto属性,也指向这个原型对象。
function Person() {}
Person.prototype.name = "张三"
Person.prototype.sayName = function () {
console.log(this.name)
}
var personA = new Person()
var personB = new Person()
personB.name = "李四"
personB.sayName() //李四
- 优点:实例对象中的方法不会多次创建,解决了内存问题
- 缺点:原型上的属性是共有属性,只能单独设置覆盖原型上的同名属性
- 原型模式+构造函数模式创建对象
从上面两种方式可以看出来将两种方式结合起来,这样实例对象就能有自己的独立属性,同时又能共享公用属性方法节省内存
function Person(name) {
this.name=name
}
Person.prototype.sayName = function () {
console.log(this.name)
}
var personA = new Person("张三")
var personB = new Person("李四")
- ES6 class类创建对象
es6提出了Class的概念,这使得创建对象的写法更接近面向对象语言的写法。通过class定义对象,默认具有constructor方法和自定义方法
class Person {
constructor(name) {
this.name = name
}
sayName() { // 等同于Person.prototype.sayName
console.log(this.name)
}
}
var personA = new Person("张三")
var personB = new Person("李四")
- 类必须有constructor方法
- 与es5一样,所有实例共享同一原型对象
- 类内部定义的方法是不可枚举的
继承
继承就是子类具有父类公有的属性和方法 假如我们将人(Preson)当作一个对象,它有一个属性(name),一个方法(sayName),然后他有一个子类工人(Worker),子类有两个属性(name、time),两个方法(sayName、sayWorkTime)
- 构造函数继承
通过call和apply方法将父类构造函数的this绑到子类上
function Person(name) {
this.name = name;
this.sayName = function () {
console.log(this.name)
};
}
function Worker(name,time){
Person.call(this,name)
this.time = time
this.sayWorkTime = function () {
console.log(this.time)
};
}
var WorkerA = new Worker("张三","8h")
console.log(WorkerA.name) //张三
console.log(WorkerA.time) //8h
WorkerA.sayName() //张三
WorkerA.sayWorkTime() //8h
- 缺点:1.子类不能访问父类原型上定义的方法(父类.peototype.方法名);2.每个子类实例上继承父类的方法都会创建一次存储在不同内存中,浪费了内存
- 原型继承
将父类的实例作为子类的原型
function Person(name) {
this.name = name;
this.info = {
age:20
}
this.sayName = function () {
console.log(this.name)
};
}
function Worker(time) {
this.time = time
this.sayWorkTime = function () {
console.log(this.time)
};
}
Worker.prototype = new Person()
var WorkerA = new Worker("8h")
WorkerA.name = "张三"
WorkerA.info.age = 26
var WorkerB = new Worker("12h")
WorkerB.name = "李四"
console.log(WorkerA.name,WorkerB.name) //张三 李四
console.log(WorkerA.time,WorkerB.time) //8h 12h
console.log(WorkerA.info==WorkerB.info) //true
- 缺点:1.子类实例不能给父类构造函数传参;2.子类共享父类的引用类型属性(示例中info对象完成相等)
- 混合继承
混合集成就是综合原型继承和构造函数继承的优点,通过构造函数继承父类实例属性、原型继承父类原型上的属性和方法
function Person(name) {
this.name = name;
this.info = {
age: 20
}
}
Person.prototype.sayName = function () {
console.log(this.name)
};
function Worker(name, time) {
Person.call(this, name)//继承父类属性
this.time = time
}
Worker.prototype = new Person()//继承父类方法
Worker.prototype.sayWorkTime = function () {
console.log(this.time)
};
var WorkerA = new Worker("张三", "8h")
var WorkerB = new Worker("李四", "12h")
console.log(WorkerA.name, WorkerB.name) //张三 李四
console.log(WorkerA.time, WorkerB.time) //8h 12h
console.log(WorkerA.info == WorkerB.info) //false
WorkerA.sayName() //张三
WorkerA.sayWorkTime() //8h
- ES6 class继承
混合集成就是综合原型继承和构造函数继承的优点,通过构造函数继承父类实例属性、原型继承父类原型上的属性和方法
class Person {
constructor(name) {
this.name = name
}
sayName() { // 等同于Person.prototype.sayName
console.log(this.name)
}
}
class Worker extends Person {
constructor(name, time) {
super(name)
this.time = time
}
sayWorkTime() {
console.log(this.time)
};
}
var WorkerA = new Worker("张三", "8h")
var WorkerB = new Worker("李四", "12h")
console.log(WorkerA.name, WorkerB.name) //张三 李四
console.log(WorkerA.time, WorkerB.time) //8h 12h
WorkerA.sayName() //张三
WorkerA.sayWorkTime() //8h
- 缺点:1.子类实例不能给父类构造函数传参;2.子类共享父类的引用类型属性(示例中info对象完成相等)
多态
多态指一个方法多种表现形式
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!