面向对象概述
面向对象,全称为Object Oriented Programming 简称OOP。属于编程范式中的命令式编程。
面向对象特征
三大特征:封装、继承、多态
封装:内部运作隐藏在对象里面,只有基本功能暴露给最终用户
继承:子类继承父类
多态:不同的对象可以共享相同方法,还能用一些特定的方法来覆盖原有的方法
原型对象
在js中,每一个对象,都有一个原型对象,而原型对象上面也有自己的原型对象,一层一层向上找,最终会找到null。
1、js中每个对象都有一个原型对象,可以通过_proto_属性来访问到对象的原型对象。
2、通过_proto_属性一直向上寻找原型对象的话,最终会找到null
3、构造函数的prototype属性指向一个对象,这个对象是该构造函数实例化出来的对象的原型对象。
4、js中的根对象是Object.prototype,Object.prototype对象是一个空对象。
5、js中的每一个对象,都是从Object.prototype对象克隆而来的。Object.prototype对象就是他们的原型对象,而Object.prototype对象的原型是null。
基于对象创建新的对象
ES5中提供Object.create()方法,可以用来克隆对象
用这个方法克隆对象时,还可以传入第二个参数,第二个参数是一个JSON对象,里面可以书写新对象的一些属性的设定
例子:
const person = {
arms: 2,
legs: 2,
walk() {
console.log('walking');
}
}
const xiejie = Object.create(person, {
name: {
value: "xiejie",
writable: false,
enumerable: true
},
age: {
value: 18,
enumerable: false
}
});
console.log(xiejie.name); // xiejie
console.log(xiejie.age); // 18
console.log(xiejie.arms); // 2
console.log(xiejie.legs); // 2
for (let i in xiejie) {
console.log(i); // name arms legs walk
}
属性特性和描述符
可以使用Object.defineProperty()来设置属性特征
value: “xiejie”, //值
writable: false, //是否能够修改
enumerable: true //是否能够遍历出来
configuration //是否能够删除
注:基于对象创建新的对象,可以继承祖辈对象的属性和方法,这其实就是一个继承关系。
原型相关的方法
- prototype 和__proto__
prototype 是构造函数上面的一个属性,指向一个对象,这个对象是该构造函数实例化出来的对象的原型对象,实例化出来的对象可以通过_proto_来找到自己的原型对象
const arr = [1,2,3,4,5];
console.log(Array.prototype); // []
console.log(arr.__proto__); // []
console.log(Array.prototype === arr.__proto__); // true
2.Object.getPrototypeOf()
和_proto_一样的用法
let arr = [1,2,3,4,5]
console.log(Object.getPrototypeOf(arr)); // []
console.log(arr.__proto__); // []
console.log(Object.getPrototypeOf(arr) === arr.__proto__); // true
3.constructor属性
查看一个对象的构造函数是啥
const arr = [1,2,3,4,5];
console.log(arr.constructor); // [Function: Array]
4、instanceof操作符
判断一个对象是否是一个构造函数的实例
const arr = [1,2,3,4,5];
console.log(arr instanceof Array); // true
console.log(arr instanceof Number); // false
5、isPrototypeOf()方法
主要是用于检测一个对象是否是一个实例对象的原型对象
const arr = [1,2,3,4,5];
console.log(Array.prototype.isPrototypeOf(arr)); // true
console.log(arr.__proto__.isPrototypeOf(arr)); // true
6、hasOwnProperty()方法
判断一个属性是定义在对象本身上面还是从原型对象上面继承而来的,如果是本身的,则返回true,如果是继承而来的,则返回false
const person = {
arms: 2,
legs: 2,
}
const xiejie = Object.create(person, {
name: {
value: "xiejie",
writable: false,
enumerable: true
},
age: {
value: 18,
enumerable: false
}
});
console.log(xiejie.hasOwnProperty("name")); // true
console.log(xiejie.hasOwnProperty("age")); // true
console.log(xiejie.hasOwnProperty("arms")); // false
console.log(xiejie.hasOwnProperty("legs")); // false
构造函数
1、构造函数创建对象
用于实例化对象的函数,我们将其称之为构造函数。
注:为了区分构造函数和普通函数,构造函数的函数名必须首字母大写
const Computer = function(name,price){
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function(){
console.log('这是一台${this.name}电脑');
}
注:之所以将方法添加在原型对象上面,是由于对于每个对象来讲,方法体都是相同的,没有必要每个对象都像属性那样单独拥有一份,所以将方法添加到原型上面,这样就达到了共享的效果。
通过new可以从构造函数中实例化出来一个对象
2、构造函数显式返回内容
如果构造函数显式的返回一个object类型的对象,那么此次运算结果最终会返回这个对象,而不是我们之前所期待的this
正常情况下,构造函数没有返回object对象,this指向实例化出来的对象
const Computer = function (name, price) {
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function () {
console.log(this); // 打印出this所指向的对象
}
const apple = new Computer("苹果", 12000);
console.log(apple.name); // 苹果
apple.showSth(); // Computer { name: '苹果', price: 12000 }
如果构造函数显式的返回一个object类型的对象,那么最终使用的是手动返回的这个对象
const Computer = function (name, price) {
this.name = name;
this.price = price;
//显式的返回一个object类型对象
return {
name: "xiejie",
showSth: function () {
console.log(this); // 打印出this所指的对象
}
}
}
Computer.prototype.showSth = function () {
console.log(this); // 打印出this所指的对象
}
const apple = new Computer("苹果", 12000);
console.log(apple.name); // xiejie
apple.showSth(); // { name: 'xiejie', showSth: [Function: showSth] }
注:如果返回的只是普通数据,那么this的指向就是实例化出来的对象
3、ECMAScript 6中类的声明
从es6开始,js开始越来越贴近其他高级语言了,可以用class来声明一个类,然后从类里面实例化对象
class Computer {
//构造器
constructor(name, price) {
this.name = name;
this.price = price;
}
//原型方法
showSth() {
console.log(`这是一台&{this.name}电脑`);
}
}
const apple = new Computer("苹果", 12000);
console.log(apple.name); // 苹果
console.log(apple.price); // 12000
apple.showSth(); // 这是一台苹果电脑
注:showSth()该方法是挂在原型对象上面的
4、静态方法
又被称为类方法,通过类来调用,不需要实例化
ES6创建静态方法,
class Computer {
//构造器
constructor(name, price) {
this.name = name;
this.price = price;
}
//原型方法
showSth() {
console.log(`这是一台${this.name}电脑`);
}
// 静态方法
static comStruct() {
console.log("电脑由显示器,主机、键盘组成");
}
}
Computer.comStruct(); // 电脑由显示器,主机、键盘组成
构造函数创建静态方法
const Computer = function (name, price) {
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function () {
console.log(`这是一台${this.name}电脑`);
}
// 静态方法 直接通过Computer这个构造函数来调用
Computer.comStruct = function () {
console.log("电脑由显示器,主机、键盘组成");
}
Computer.comStruct(); // 电脑由显示器,主机、键盘组成