JavaScript面向对象编程
JavaScript面向对象开发常见问题
此文章适合还未接触过大型项目开发和准备步入职场的小白
一、 什么是面向对象
刚学习js就听说过万物皆对象,在实际工作中确实如此,项目中把需要的每一个需求或者一个部分,封装成一个类,从而提升代码的可复用性和维护性。
在实际工作中面向对象开发模式非常常见,可以理解为类似装修,封装了一个家具类、电器类等等
二、对象的创建方式
1、构造函数
在学校里老师都会教一个叫构造函数的东西,并且一般都是这样书写的:
function Person(name, age) {
this.name = name;
this.age = age;
this.print= function() {
console.log('姓名:' + this.name + ' ' + '年龄:' + this.age );
}
}
//相应的创建方式
var person1 = new Person("孙悟空",18)
首先构造函数也是一种函数,并没有什么特别之处
2、ES6 class创建
在学校几乎没有太接触过class这个概念,在网上了解过一些,具体概念这里不再陈述,直接说一些简单的例子,下面class的写法等同上面构造函数的效果
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
print = function(){
console.log('姓名:' + this.name + ' ' + '年龄:' + this.age );
}
}
var person1 = new Person("孙悟空", 18)
不知道看到这里你是否有些疑惑。我在学习的时候我就产生了一个疑惑,上一部分构造函数结构分明,但是ES6中class中多了许多东西,construct是什么?为什么属性写在了construct里,而方法写在了外部?为什么属性前有this而方法并没有?
三、构造函数与class
首先我们先来看构造函数。构造函数在声明的时候,为什么要做this.name = name,this.age = age?
1、首先this粗略来说,指向创建的实例对象,也就是这里的person1;
2、this.name、this.age表明实例对象上有两个属性:一个叫name,一个叫age,还有一个方法叫:print;
3、实例对象上这两个属性值,在构造函数里并没有写死,具体值由创建实例对象的时候实参决定。
由此构造函数,我们可以创建不同的“Person”实例对象,我们甚至可以创建师徒四人出来
//接收两个参数
function Person(name, age) {
this.name = name;
this.age = age;
this.print = function () {
console.log('姓名:' + this.name + ' ' + '年龄:' + this.age);
}
}
//实例化时传参
var person1 = new Person("孙悟空", 18);
var person2 = new Person("唐僧", 35);
var person3 = new Person("猪八戒", 40);
var person4 = new Person("沙和尚", 55);
而如果我不需要不同的对象,我只想要孙悟空,我想要很多个“孙悟空”,我这里压根就不需要传值
//不需要形参接收参数
function Person() {
this.name = "孙悟空";
this.age = 18;
this.print = function () {
console.log('姓名:' + this.name + ' ' + '年龄:' + this.age);
}
}
//实例化时不需要传参
var person1 = new Person();
var person2 = new Person();
var person3 = new Person();
var person4 = new Person();
说这些很简单,接下来我们来看class
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
print = function(){
console.log('姓名:' + this.name + ' ' + '年龄:' + this.age );
}
}
var person1 = new Person("孙悟空", 18)
还是上面给过的一模一样的代码,通过这个class类,我们也可以创建很多个实例,只需要在new的时候传不同的参数即可
如果这里我不需要灵活创建对象呢?我就需要很多个孙悟空
代码如下:
class Person{
name = "孙悟空"
age = 18
print(){
console.log('姓名:' + this.name + ' ' + '年龄:' + this.age);
}
}
var person1 = new Person();
var person2 = new Person();
var person3 = new Person();
var person4 = new Person();
和构造函数一样,不用接收参数了。但是特殊的是:construct不见了,this也不见了
四、construct有什么用
定义: constructor 是类的构造函数,他是方法,在new实例化的时候,会自动调用这个函数,这一句话就可以解决刚刚的问题
1、首先construct在实例化对象的时候,会自动调用,如果需要传递参数,可以在construct中接收
2、construct是实例化对象的一个方法,它是一个函数。如果在其中定义的属性不加上this,是会报错的。原因是:this永远指向调用此函数的人,这里实例化对象的时候谁在调用construct?就是那个对象,所以给这个对象添加属性或方法时,需要加上this
3、construct在实例化对象时会自动调用,所以可以在其中调用函数
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
// 在constru中调用对象的print方法
this.print()
}
print(){
console.log("我是" + this.name);
}
}
var person1 = new Person("孙悟空", 18)
控制台输出:
注意,我这里只new了一个对象,并没有打印输出任何东西。之所以控制台打印了信息,是因为这里在实例化对象的时候自动会调用construct,而在construct中调用了print方法
简单总结:
1、construct会在实例化对象的时候调用,他是个函数,所以在其中定义属性或者方法要写this;
2、需要接收参数可以在construct中接收;
3、construct会被立刻调用,需要调用的方法也可以写在其中。
五、extends、super
除了构造函数和class,在面向对象编程中还会遇到继承的问题
继承可以理解为,一个类去继承另一个类,子类可以获取到父类的属性和方法。在子类中如果要使用construct,必须要调用super(),因为子类本身并没有自己的this对象,他必须从父类继承;如果不使用construct,会自动调用父类的construct
//父类
class Person {
constructor(name, age) {
this.name = name;
this.age = age
}
print() {
console.log('我是父类的print' + '姓名:' + this.name + ' ' + '年龄:' + this.age)
}
}
//子类
class Man extends Person {
constructor(name, age) {
super(name, age)
}
print() {
super.print();
console.log('我是子类的print' + '姓名:' + this.name + ' ' + '年龄:' + this.age)
}
}
let person1 = new Man("孙悟空", 18)
console.log(person1.name, person1.age)
person1.print()
上述代码出现了两次super
第一次super作为函数调用,此处可以理解为父类的构造函数,这里实际上原理是改变了this指向问题,Person.prototype.constructor.call(this, props)
第二次super作为对象来使用,指向父类的原型对象,这里其实动作是 super.print.call(this)
六、总结
在面向对象的开发中,这些都是很基础的,如何使用class创建,construct是什么?怎么用?extends继承和super的使用原理,这些最基础的都需要掌握。