首先【什么是原型】
每一个对象都有他的原型对象,他可以使用原型对象上的所有属性和方法
如果原型对象没有,我们可以进行添加
获取原型的方法
- 是通过对象的__proto__获取(实例)
- 是通过构造函数的prototype属性拿到属性(构造函数中的this指向new创建的对象)
- 通过类的prototype属性
let cat={ name:"mm"}
//通过对象的__proto__获取
cat.__proto__.eat = function(){console.log(“吃鱼”)}
cat.eat();
function Cat(name,age){
this.name = name;
this.age = age;
}
let cat = new Cat("喵喵",2);
//通过构造函数的prototype添加了新的方法
Cat.prototype.eat = function(){console.log("吃鱼")}
cat.eat();
原型有什么用?
比如想要输出XX年XX月XX日这种格式方法
let date = new Date();
//这里利用原型添加新的方法
Date.prototype.formate = function(){
let year = this.getFullYear();
let month = this.getMonth()+1;
let date = this.getDate();
return `${year}年${month}月${date}日`
}
//说明this指向的是函数调用的对象,而不是声明的函数的对象
date.formate()
面向对象的程序设计
前面获取原型的第三个方法说利用类,下面说一下ES6类的基本语法(与ES5进行区别)
可以看到是通过类的prototype属性进行添加新方法。
class Cat{
constructor(name,age){
this.name = name;
this.age = age;
}
}
Cat.prototype.eat = function(){
console.log("吃鱼")
}
let cat = new Cat("喵喵",2);
cat.eat();
继承(ES6与原型)
对于继承,es6和es5有很大区别,es5是利用了原型链进行继承,es6则利用了class类+extends新特性,较之前相比更为方便。
class User{
constructor(username,age){
this.username = username;
this.age = age;
}
login(){
console.log("登录");
}
}
//使用了extends去继承
class Admin extends User{
deletePerson(){
console.log("删除一个管理员")
}
}
let admin = new Admin();
admin.login();
admin.deletePerson();
如何使用ES5继承:prototype
function User(username,password){
this.username =username;
this.password = password;
this.login = function(){
console.log("登录")
}
}
function Admin(){
this.deletePerson = function(){
console.log("删除一个人")
}
}
Admin.prototype = new User(); //核心重点,将prototype挂在new出来的实例上,构成原型链
let admin = new Admin();
admin.login();
终点是Object
原型链
可以看到,可以将proto看成指针一样的东西,prototype则是自带属性。
通过下面代码判断来进一步理解__proto__和prototype
let obj = {};
let arr = [];
let fn = function() {}
obj.__proto__ == Object.prototype // true
arr.__proto__ === Array.prototype // true
fn.__proto__ == Function.prototype // true
这里比较绕,看图帮助理解一下。
图片来源栗耗嘤
参考资料: 晓舟报告 推荐看他的b站视频讲解会更清晰。