面向对象编程 (Object Oriented Programming҅,OOP) 一种编程范式,它具有属性和方法的对象。
原型对象
JavaScript 都有一个原型对象,原型对象也有自己的原型对象,最终会到达null。
原型相关方法
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
Object.getPrototypeOf()
方法
查找一个对象的原型对象
let arr = [1,2,3,4,5]
console.log(Object.getPrototypeOf(arr)); // []
console.log(arr.__proto__); // []
console.log(Object.getPrototypeOf(arr) === arr.__proto__); // true
constructor
属性
可以看到一个对象的构造函数是什么,也就是这个对象是如何得来的
const arr = [1,2,3,4,5];
console.log(arr.constructor); // [Function: Array]
instanceof
操作符
一个对象是否是一个构造函数的实例,是返回 true,否则false
const arr = [1,2,3,4,5];
console.log(arr instanceof Array); // true
console.log(arr instanceof Number); // false
isPrototypeOf()
方法
返回一个布尔值,主要用于一个对象是否是一个实例对象的原型对象
const arr = [1,2,3,4,5];
console.log(Array.prototype.isPrototypeOf(arr)); // true
console.log(arr.__proto__.isPrototypeOf(arr)); // true
hasOwnProperty()
方法
判断一个属性定义是在对象本身还是从原型对象上面继承而来的,是返回 true ,否则 false
const person = {
arms: 2,
legs: 2,
}
const xiejie = Object.create(person, {
name: {
value: "bai",
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
基于对象创建新对象
Object.create()
可以用来克隆对象
const person = {
arms: 2,
legs: 2,
walk() {
console.log('walking');
}
}
const xiejie = Object.create(person);
console.log(xiejie.arms); // 2
console.log(xiejie.legs); // 2
xiejie.walk(); // walking
console.log(xiejie.__proto__ === person); // true
//也可以传入第二个参数,参数为 JSON对象
const person = {
arms: 2,
legs: 2,
walk() {
console.log('walking');
}
}
const bai = Object.create(person, {
name: {
value: "bai",
writable: false,//是否能被修改
enumerable: true//是否能被遍历
},
age: {
value: 18,
enumerable: false
}
});
console.log(bai.name); // bai
console.log(bai.age); // 18
console.log(bai.arms); // 2
console.log(bai.legs); // 2
for (let i in bai) {
console.log(i); // name arms legs walk
}
//--- 也可以继承祖辈的对象的属性和方法,也就是一个继承关系
const person = {
arms: 2,
legs: 2,
walk() {
console.log('walking');
}
}
const bai = Object.create(person, {
name: {
value: "bai",
writable: false,
enumerable: true
},
age: {
value: 18,
enumerable: false
},
born: {
value: "chengdu"
}
});
const son = Object.create(xiejie, {
name: {
value: "xizhi"
},
age: {
value: 0
}
})
console.log(son.name); // xizhi
console.log(son.age); // 0
console.log(son.born); // chengdu
console.log(son.arms); // 2
console.log(son.legs); // 2
son.walk(); // walking
console.log(xiejie.isPrototypeOf(son)); // true
console.log(person.isPrototypeOf(son)); // true
//son 对象是 bai 克隆而来,形成了一条原型链,无论 person,bai 属性方法 son都能继承到
构造函数
用于实例化对象的函数,将其称为构造函数,为了规范命名首字母大写
const Computer = function(name,price){
this.name = name;
this.price = price;
}
Computer.prototype.showSth = function(){
console.log(this); // 打印出 this 所指向的对象
console.log(`这是一台${this.name}电脑`);
}
const apple = new Computer('苹果',12000);
console.log(apple.name);// 苹果
console.log(apple.price);// 12000
apple.showSth();// Computer { name: '苹果', price: 12000 } 这是一台苹果电脑
const asus = new Computer('华为',5000);
console.log(asus.name);// 华为
console.log(asus.price);// 5000
asus.showSth();// Computer { name: '华为', price: 5000 } 这是一台华为电脑
正常没有返回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: "bai",
showSth: function () {
console.log(this); // this 指向的对象
}
}
}
Computer.prototype.showSth = function () {
console.log(this); // this 指向的对象
}
const apple = new Computer("苹果", 12000);
console.log(apple.name); // bai
apple.showSth(); // { name: 'bai', showSth: [Function: showSth] }
//返回object对象情况
const Student = function () {
this.name = 'bai';
return {
name: 'song'
};
}
const obj = new Student();
console.log(obj.name); // song
//返回普通数据情况
const Student = function () {
this.name = 'bai';
return 'song';
}
const obj = new Student();
console.log(obj.name); // bai
ECMAScript 6 中 类的声明
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(); // 这是一台 华为 电脑
//name 和 price 数挂在原型对象上的证明如下
Computer.prototype.showSth(); // 这是一台 undefined 电脑
//Computer.prototyp 指向实例对象的原型对象,这里同样你成调到showSth()方法
静态方法
用于不需要实例化对象,直接调用方法
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(); //电脑