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等没有什么太大区别了。

 五、总结:

    原型与原型链是前端面试经常问到的问题。而继承是码农必须掌握的一种思维。代码一定要‘抠搜’的使用,能多用一次就多用一次,能少写一些就不多写。今天要比昨天更进步一些。

posted @ 2022-07-06 14:18  WangED  阅读(80)  评论(0)    收藏  举报