【javascript】面向对象 原型
面向对象概念
-
历史
面向过程编程语言: 汇编语言、C语言
面向对象编程语言: C++、Java、JavaScript、Python -
思想
面向过程编程思想:只关心数学逻辑。
面向对象编程思想:将生活逻辑映射到我们程序中。
- 步骤:
1、找出实体
2、分析实体属性和功能
3、让实体之间相互作用
封装创建对象的函数
- 工厂模式:
- 原料
- 加工
- 出厂
- 【注】凡是满足上述三个步骤创建对象的函数,我们把它叫做工厂方法。
function createPerson(name, sex){
//1、原料
var obj = new Object();
//2、加工
obj.name = name;
obj.sex = sex;
obj.showName = function(){
alert("我的名字叫" + this.name);
}
obj.showSex = function(){
alert("我的性别是" + this.sex + "的");
}
//3、出厂
return obj;
}
var p1 = createPerson("blue", "男");
p1.showName();
p1.showSex();
var p2 = createPerson("red", "女");
p2.showName();
p2.showSex();
alert(p1.showName === p2.showName); //false
通过new创建对象
- 如果,我们某一个函数,使用new运算符去调用
- 当前函数中的this指向新创建的对象
- 自动去完成1、原料和3、出厂操作
- 这种通过new调用函数,叫做构造函数,构造函数可以构造对象,
【注】构造函数一般情况下首字母大写
var arr1 = new Array(10, 20, 30);
var arr2 = new Array(40, 50, 60);
alert(arr1.push === arr2.push); //true
function Person(name, sex){
//1、原料
// var obj = new Object();
// this = new Object();
//2、加工
this.name = name;
this.sex = sex;
this.showName = function(){
alert("我的名字叫" + this.name);
}
this.showSex = function(){
alert("我的性别是" + this.sex + "的");
}
//3、出厂
// return obj;
//return this;
}
var p1 = new Person("blue", "男");
p1.showName();
p1.showSex();
var p2 = new Person("red", "女");
p2.showName();
p2.showSex();
alert(p1.showName === p2.showName); //false
prototype 原型对象
- 概念:每一个函数上,都有一个原型对象prototype
- 用在构造函数上,我们可以给构造函数的原型prototype,添加方法
- 如果我们将方法添加到构造函数的原型prototype对象上,
- 构造函数构造出来的对象共享原型上所有的方法。
-
构造函数构造出来的对象,有一个属性__proto__,指向构造出这个对象的构造函数的原型。
-
Person构造函数添加方法,添加在构造函数的原型上prototype
-
Person.prototype.showName = function(){ }
Person.prototype.showName = function(){
alert("我的名字" + this.name);
}
Person.prototype.showSex = function(){
alert("我的性别" + this.sex);
}
var p1 = new Person("blue", "男");
p1.showName();
p1.showSex();
var p2 = new Person("red", "女");
p2.showName();
p2.showSex();
alert(p1.showName === p2.showName); //false
- 通过构造函数的原型添加方法
Dog.prototype = {
run: function(){
alert(this.name + "会飞快的奔跑");
},
showSelf: function(){
alert(`这是一个${this.type}的,${this.age}岁的,叫${this.name}的小狗`);
}
}
instanceof 关键字
- 功能:判断某一个对象是否是这个构造函数构造出来的。
var xiaobai = new Dog({
name: "小白",
type: "比熊",
age: 3
});
// alert(xiaobai instanceof Dog);
alert(xiaobai instanceof Object);
面向对象,继承、封装(封装构造函数)、多态。
- 面向对象是一个编程思想,支撑面向对象编程思想的语法是类(ECMA6之前没有类这个概念)和对象,构造函数充当类的角色。
- 构造函数和对象实现面向对象程序的时候,体现出 继承、 封装、 多态的特点。
继承
- 分类更加细分的构造函数。继承
function Teddy({name, type, age, color}){
//this = new Object();
//1、继承父一级构造函数所有的属性
//构造函数的伪装
Dog.call(this, {
name: name,
type: type,
age: age
})
//添加自己的属性
this.color = color;
//return this;
}
- 原型链继承
- Teddy.prototype[funcName] = Dog.prototype[funcName];
// Teddy.prototype = Dog.prototype; 非常错误的写法
for(var funcName in Dog.prototype){
Teddy.prototype[funcName] = Dog.prototype[funcName];
}
Teddy.prototype.showColor = function(){
alert(this.color);
}
对象拷贝
var obj1 = {
a: 10,
b: 20,
c: 30
};
var obj2 = {};
for(var attr in obj1){
obj2[attr] = obj1[attr];
}
obj2.c = 100;
console.log(obj1);//{"a":10,"b":20,"c":30}
console.log(obj2);//{"a":10,"b":20,"c":100}
多态
-
在子一级构造函数重写showSelf方法,只会在子一级生效,并不会影响父一级构造函数的方法。
-
继承和多态同一件事情的两种完全不同的侧重:
- 继承:侧重是从父一级构造函数,继承到的属性和方法。
- 多态:侧重是,子一级,自己重写和新增的属性和方法。
Teddy.prototype.showSelf = function(){
alert(`这是一个${this.type}的,${this.age}岁的,是${this.color}的,叫${this.name}的小狗`);
}
Teddy.prototype.showColor = function(){
alert(this.color);
}
var xiaohong = new Teddy({
name: "小红",
type: "泰迪",
age: 10,
color: "红色"
})
xiaohong.showSelf();
var xiaohei = new Dog({
name: "小黑",
type: "拉布拉多",
age: 5
});
xiaohei.showSelf();
ECMA6 CLASS语法
传统方法创建对象
function Person(name, sex, age){
this.name = name;
this.sex = sex;
this.age = age;
}
Person.prototype.showSelf = function(){
alert(`我是一个叫${this.name},今年${this.age}岁的${this.sex}孩`);
}
对象继承
//白领人
function Worker(name, sex, age, job){
//1、构造函数的伪装 -- 继承父级的属性
Person.call(this, name, sex, age);
this.job = job;
}
//2、原型链 继承父一级的方法
//<1>通过for...in遍历继承
/* for(var funcName in Person.prototype){
Worker.prototype[funcName] = Person.prototype[funcName];
} */
//<2>Object.create()
// Worker.prototype = Object.create(Person.prototype);
//<3>调用构造函数继承
Worker.prototype = new Person();
Worker.prototype.showJob = function(){
alert("我的工作是" + this.job);
}
var w1 = new Worker("小米", "男", 20, "程序员");
w1.showSelf();
w1.showJob();
ECMA6 class创建对象
class Person{
//class属性添加
constructor(name, sex, age){
this.name = name;
this.sex = sex;
this.age = age;
}
showSelf(){
alert(`我是一个叫${this.name},今年${this.age}岁的${this.sex}孩`);
}
}
var p1 = new Person("blue", "男", 18);
p1.showSelf();
ECMA6对象继承 extend
class Worker extends Person{
constructor(name, sex, age, job){
//1、继承到父一级的属性
super(name, sex, age);
this.job = job;
}
showJob(){
alert("我的工作是" + this.job);
}
}
var w1 = new Worker("小米", "男", 20, "程序员");
w1.showSelf();
w1.showJob();