目的
- 什么是面向对象编程
- 复习关键字new并且理解它所做的四件事
- 在我们的代码中使用构造函数来优化我们得代码
- 使用call和apply来重构构造函数
面向对象编程的定义
- 基于对象概念的编程模式
- 这些对象是由类创建的,我们可以把类想象成一个蓝图,把这些对象叫做类的实例
- 尽量让类抽象化和模块化
JavaScript中的面向对象编程
JavaScript 中没有内置的类,但是我们可以用函数和对象去模拟
1. 创建对象
想象我们要创建一些house对象,他们都有 bedrooms, bathrooms, numSqft 属性
var house = {
bedrooms: 2,
bathroom: 2,
sqFeet: 1000
}
var house1 = {
bedrooms: 2,
bathroom: 2,
sqFeet: 1000
}
var house2= {
bedrooms: 2,
bathroom: 2,
sqFeet: 1000
}
// 想象一下 我们如果有 1000个房子
解决办法 创建一个函数来构建这些类似的“房子”对象,而不是创建无数个不同的对象
1.构造函数
让我们使用一个函数作为每个房子应该是什么的蓝图——我们把这些函数称为“构造函数”
function House(bedrooms, bathrooms, numSqft){
this.bedrooms = bedrooms
this.bathrooms = bathrooms
this.numSqft = numSqft
}
注意一些事:
- 函数名的大小写
- 关键字this!!!
- 我们将属性附加到关键字“this”上。我们希望关键字“this”指的是我们将从构造函数函数中创建的对象,我们该如何做呢?
2.使用构造函数创建对象
function House(bedrooms,bathrooms,numSqft) {
this.bedrooms = bedrooms
this.batnrooms = bathrooms
this.numSqft = numSqft
}
// test
var firstHouse = Houes(2,2,1000)
firstHouse //undefined ....
为什么不起作用!!
- 我们没有从函数中返回任何东西所以我们的House函数返回没有定义的
- 我们没有显式地绑定关键字'this'或将它放在声明的对象中。这意味着关键字“This”的值将是全局对象,这不是我们想要的!
解决办法 使用关键字new
function House(bedrooms,bathrooms,numSqft) {
this.bedrooms = bedrooms
this.batnrooms = bathrooms
this.numSqft = numSqft
}
// test
var firstHouse = new House(2,2,1000);
firstHouse.bedrooms; // 2
firstHouse.bathrooms; // 2
firstHouse.numSqft; // 1000
思考关键字new做了什么
- 首先, 关键字new创建了一个新的空对象
- 然后,它把关键字this设置到了这个空对象上
- 添加一条 ‘return this’ 在函数的末尾
- 执行原型连接操作 {它将一个属性添加到名为“proto”的空对象上,这个空对象将构造函数上的prototype属性链接到空对象上(后面会详细介绍)}
练习 为Dog创建一个构造函数,每个Dog都有姓名(name),年龄(age)属性, 还有bark方法
function Dog(name, age) {
this.name = name;
this.age = age;
this.bark = function() {
console.log(this.name + ' 汪汪汪')
}
}
// test
var dog1 = new Dog("小黄",1)
var dog2 = new Dog("小美",2)
dog1.bark() // 小黄 汪汪汪
dog2.bark() // 小美 汪汪汪
3.多个构造函数
分别为 Car 和 Motorcycle 创建一个构造函数
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
this.numWheels = 4
}
function Motorcycle(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
this.numWheels = 2
}
摩托车的功能有重复。有没有办法“借用”汽车功能并在摩托车功能中调用它? 使call/apply
function Car(make, model, year){
this.make = make;
this.model = model;
this.year = year;
this.numWheels = 4;
}
function Motorcycle(make, model, year){
//using call
Car.call(this, make, model, year)
this.numWheels = 2
}
function Motorcycle(make, model, year){
// using apply
Car.apply(this, [make,model,year]);
this.numWheels = 2;
}
function Motorcycle(){
// 我们甚至不需要传递参数!
// 更好的用法是使用apply和arguments
Car.apply(this, arguments);
this.numWheels = 2;
}
小结一下
- 面向对象编程是一种基于对象被一种蓝图构建的模式,我们使用面向对象写更多模块化和可共享的代码
- 在支持OOP的语言中,我们将这些蓝图称为“类”,而从它们创建的对象称为“实例”
- 由于我们在JavaScript中没有内置的类支持,所以我们使用函数来模拟类。这些构造函数通过使用new关键字创建对象
- 我们可以通过call或apply来避免多个构造函数中的重复