JavaScript中原型与原型链
JavaScript中原型与原型链
一、原型基本概念:
1.什么是原型:JS的任何一个对象都拥有一个“原型对象”,他可以使用自己原型对象上的 所有属性与方法。
2.获取原型的方法:
1)__proto__获取方式:注意__是两个下划线。
// 1. 利用__proto__来调用原型
let cat = {
name : '伽罗'
}
// 现在通过 cat.__proto__.eat 为cat的原型添加了一个方法 eat 这个方法来输出吃饭
cat.__proto__.eat=function() {
console.log('吃饭')
}
cat.eat()

2)通过构造函数prototype 属性获取。
function Cat(name,age){
this.name=name
this.age=age
}
let cat = new Cat('伽罗',2)
Cat.prototype.eat=function(){
console.log('吃饭')
}
cat.eat()

3)类的prototype属性。通过es6新增class类 来进行调用。
二、继承:
上述已经学习了原型是什么、如何引用原型。但是为什么要引用原型?了解之前先学习一个概念——继承。在java等类C语言当中存在的一个概念性问题。
1.定义:子类可以继承父类的全部公开的属性和方法。
2.举例:现在有一个博客系统。分为管理员和普通用户,普通用户只能登录,而管理员不光能登录还能删除用户。
如果正常写,两个类一个管理员一个用户,两者毫无关系。
public class user {
String name;
String password;
public static void login() {
System.out.print("普通用户登录");
}
}
public class admin{
String name;
String password;
public static void login() {
System.out.print("管理员登录");
}
public static void delete () {
System.out.print("删除用户");
}
}
但是这么写,代码冗余,同样的属性名字和密码、同样的方法登录,两者都有唯一不同的就是管理员多出删除。如果使用继承,将管理员定义成,子类继承父类用户。这样就优化代码提高复用性。
public class user {
String name;
String password;
public static void login() {
System.out.print("普通用户登录");
}
}
public class admin extends user{
public static void delete () {
System.out.print("管理员登录");
}
}
java当中可以使用这种思想,JS也可以使用,但是ES5当中没有继承的概念,那么如何实现,就只能使用原型来模拟继承。
因为Admin 可以使用自己的原型全部的方法。如果让自己的原型称为User的一个实例。即=new User()。那就相当于Admin 可以通过原型使用User的全部属性与方法。就实现了继承的思想。

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()
let admin=new Admin()
admin.login()

3.原型的作用:
1)模拟继承
2)规范日期:通过下述代码可以获取到当前日期,显示为 Wed Jul 06 2022 13:20:28 GMT+0800 (GMT+08:00)。但是 我不想要这种格式输出显示,我想显示成‘年/月/日’的格式,那么如何修改。
let date = new Date()
console.log(date);
所以使用原型,来进行设定。无论是JS原生的还是,自己定义的都可以通过这种方法。
let date = new Date()
Date.prototype.format = function() {
let year = this.getFullYear()
// 月份输出从0 开始 所以加一
let month = this.getMonth()+1
let date = this.getDate()
return `${year}年${month}月${date}日`
}
console.log(date.format());

三、原型链:
1.定义:现在已经理解了什么是原型,那么原型是否还有原型呢,那原型的原型还有原型吗.....。答案是肯定的。这条链,就称为原型链。

2.尽头:那么了解了原型链,就要知道原型链的尽头就是object。

还是管理员的例子,现在admin想调用login()。但是User() 里面没有login() 那么就会顺着原型链,继续向上寻找,直到找到objec,如果存在login()则输出,如果没有则报错。
function User(username,password){
this.username=username
this.password=password
// this.login=function(){
// console.log('登录');
// }
}
function Admin(){
this.deletePerson=function(){
console.log('删除用户');
}
}
// 对objcet 上原型添加登录方法。
Object.prototype.login = function(){
console.log('Object上的登录');
}
User.prototype = new Object()
Admin.prototype = new User()
let admin=new Admin()
admin.login()
但因为对Object的原型添加了登录方法。所以所有引用类型都可以直接使用login()方法。一定要注意这个问题。
// 在上述代码后面定义一个数组后调用
let arr=[1,2,3] arr.login()
四、ES6
那么在ES6之前不可以使用类,而JS在ES6之后引入了类的概念,那么就可以直接使用继承的思维了。
上述关于管理与普通用户的例子就可以修改ES6之后的写法。
class User{
constructor(username,password){
this.username=username
this.password=password
}
login(){
console.log('登录');
}
}
class Admin extends User{
deletePerson(){
console.log('删除用户');
}
}
let admin = new Admin()
admin.login()

可以看出 写法上与类C语言,如java等没有什么太大区别了。
五、总结:
原型与原型链是前端面试经常问到的问题。而继承是码农必须掌握的一种思维。代码一定要‘抠搜’的使用,能多用一次就多用一次,能少写一些就不多写。今天要比昨天更进步一些。

浙公网安备 33010602011771号