获取原型的方法
1.通过对象的__proto__获取
2.通过构造函数的prototype属性获取到原型
3.通过类的prototype属性(Es6)
举个栗子
function Person(){
this.name = "小钟";
}
Person.prototype.showMyName =()=>{
console.log("我是小钟")
}
let smallClock = new Person();
smallClock.showMyName(); // 我是小钟
Person.prototype是一个对象,叫“原型对象”。这里我们在原型对象Person.prototype上面挂载了
showMyName这个方法。
smallClock是构造函数Person实例化出来的一个对象。smallClock上为什么也有showMyName这个方法呢?
因为实例对象smallClock与原型对象Person.prototype之间存在一个隐式链接。这个隐式链接就
__proto__原型链。smallClock自身是没有showMyName方法的,但它有__proto__原型链,当
smallClock在自身的方法中找不到showMyName时,就会通过它原有的__proto__原型链继续
向上查找它的原型对象Person.prototype,通过原型链,实例化对象smallClock也可以拥有原
型对象Person.prototype上的方法。
再举一个栗子对应第一条通过对象的__proto__获取
let fish={
name:"我不喜欢吃鱼"
}
fish.__proto__.eat=()=>{
console.log("有鱼刺")
}
fish.eat();
//fish.__proto__这个就是它的原型,给他的原型上加一个eat方法,
又一个栗子对应第二条通过构造函数的prototype属性获取到原型
这里简单说一下什么是构造函数,构造函数也是一个函数,比较特殊的是构造函数可以new()出一个新的函数,并在new的过程中初始化该函数。
function Fish(name,age){
this.name=name;
this,age=age
}
let fish=new Fish("鳕鱼",10);
Fish.prototype.eat=()=>{
console.log("鱼刺少,可以吃")
}
fish.eat();
原型对象在实际开发中的用处(让时间以xx年xx月xx日的形式展示出来)
let studyTime=new Date();
Date.prototype.newTime=function(){
let studyYear=this.getFullYear();
let studyMonth=this.getMonth()+1;
let studyDate=this.getDate();
return `${studyYear}年${studyMonth}月${studyDate}日`
}
console.log(studyTime.newTime()) //2022年9月16日
1.类的基本语法
class Person{
constructor(name,age){
this.name = name;
this.age = age;
}
Speak(){
return '我的名字是 ' + this.name+“今年”+this.age;
}
}
var person1 = new Person('小钟',22); //person1 是通过类 Person 实例化出来的对象
console.log(person1.Speak());
// new Person和刚才上面提到的构造函数new一个new Fish很像,其实可以这样理解,Es5创建对象用
构造函数,二Es6用Class关键字创建一个类,类里面可以加一些属性和方法,
Person.prototype.Like=()=>{
return "喜欢跑步、滑板、射箭、拳击"
}
console.log(person1.Like()) //喜欢跑步、滑板、射箭、拳击
Object.assign(Person.prototype,{
Run:function(){
return "经常晨跑"
}
})
console.log(person1.Run()) //经常晨跑
person1.__proto__.Eat=()=>{
return "喜欢喝中杯标准糖去冰厚芋泥啵啵奶茶"
}
console.log(person1.Eat()) //喜欢喝中杯标准糖去冰厚芋泥啵啵奶茶
3.class类的继承
class SmallClock extends Person{
Listen(){
return "很喜欢听毛不易《平凡的一天》"
}
}
let smallClock1=new SmallClock("小钟",23)
console.log(smallClock1.Run()) //经常晨跑
console.log(smallClock1.Listen()) //很喜欢听毛不易《平凡的一天》
与实际开发结合,例如一个系统,有两种用户,普通用户和管理员,普通用户有用户名和密码,可以登录,管理员除了有用户名和密码外还有更大的权限,比如它可以删除用户
class User{
constructor(name,password){
this.name=name;
this.password=password
}
login(){
console.log("登录成功")
}
}
class Admin extends User{
deleteUser(){
console.log("删除某个用户")
}
}
let newPeople=new Admin();
newPeople.deleteUser(); //删除某个用户
newPeople.login(); //登录成功
用原型如何实现继承呢?(Es5继承)
由于Es5中没有类,只能定义一个构造函数
function User(name,password){
this.name=name;
this.password=password;
this.login=function(){
console.log("登录成功")
}
}
function Admin(){
this.deletePerson=function(){
console.log("删除某个用户")
}
}
Admin.prototype=new User();
let admin=new Admin();
admin.login(); //登录成功
Admin中没有login方法,然后会去它的原型上面找,Admin的原型等于new User(),User中
有login方法,那假设如果User中也没有login()呢,它是否会继续向上找?
来做一个简单的测试,将下面的代码注释掉
// this.login=function(){
// console.log("登录成功")
// }
报错:admin.login is not a function
没有,再向上一层找,上一层要怎样定义呢?
function User(name,password){
this.name=name;
this.password=password;
}
function Admin(){
this.deletePerson=function(){
console.log("删除某个用户")
}
}
Object.prototype.login=()=>{
console.log("最上层")
}
Admin.prototype=new User();
let admin=new Admin();
admin.login(); //最上层
这就是基于原型链实现的一个在Object,最上层的原型上添加方法
let eat=[1,2,3];
eat.login(); //最上层
此时,所有对象的最上层都是Object.prortotype
注意点
类不存在变量提升(hoist)
new ToDo(); // ReferenceError
class ToDo {} //使用在前定义在后会报错,所以继承时,子类应定义在父类之后