美文网首页
1.web前端基础储备之—js的面向对象风格以及原型和原型链

1.web前端基础储备之—js的面向对象风格以及原型和原型链

作者: Feng_Du | 来源:发表于2021-02-22 17:32 被阅读0次

    javascript是面向对象风格,基于原型的语言。

    目标:了解js面向对象和原型原型链的关系

    面向对象(OOP)的特点?

    封装、继承、多态

    1.封装:是将数据和代码捆绑到一起,对象的某些数据和代码可以是私有的,不能被外界访问,以此实现对数据和代码不同级别的访问权限。防止了程序相互依赖性而带来的变动影响,面向对象的封装比传统语言的封装更为清晰、更为有力。有效实现了两个目标:对数据和行为的包装和信息隐藏。

    2.继承:简单地说就是一种层次模型,这种层次模型能够被重用。层次结构的上层具有通用性,但是下层结构则具有特殊性。在继承的过程中类则可以从最顶层的部分继承一些方法和变量。类除了可以继承以外同时还能够进行修改或者添加。通过这样的方式能够有效提高工作效率。在这里举一个例子,当类X继承了类Y后,此时的类X则是一个派生类,而类Y属于一个基类。 继承是从一般演绎到特殊的过程,可以减少知识表示的冗余内容,知识库的维护和修正都非常方便。更有利于衍生复杂的系统。

    3.多态:多种形态,指不同事物具有不同表现形式的能力。多态机制使具有不同内部结构的对象可以共享相同的外部接口,通过这种方式减少代码的复杂度。一个接口,多种方式。比如:相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息通过某一种标识可以产生不同的结果,这种现象称为多态性。

    在javascript中OOP的呈现。

    1.封装
    基于构造函数的封装:

     function schoolmate(name,age,grade){
                this.name = name;
                this.age = age;
                this.grade = grade;
        }
        let g1=new schoolmate('赵云','11','88');
        let g2=new schoolmate('韩信','12','100');
        console.log(g1,g2)
    /*ps:当然还有其他方式不一一列举*/
    

    2.继承
    想要了解js中的继承我们先看看什么是javascript的原型和原型链:[1]
    基于原型的继承:

      // 父类方法(Superclass)
      function Superclass() {
          this.supName = "我是父类"
      }
      // 父类添加原型方法
      Superclass.prototype.showSupName = function () {
          console.log(this.supName)
      }
      //子类(Subclass)
      function Subclass() {
          this.subName = "我是子类"
      }
      /**
       * 1 让子类能访问父类的方法
       * 2 让子类的constructor属性指向自身(constructor属性是对函数本身的引用)
       **/
      Subclass.prototype = new Superclass();
      Subclass.prototype.constructor = Subclass
      // 子类添加原型方法
      Subclass.prototype.showSubName = function () {
          console.log(this.subName)
      }
      // 子类调用父类方法
      var sub = new Subclass();
      sub.showSupName();
    
    /*ps:如果想要继承父类的属性可调用父类的function.call(thisArg, arg1, arg2, ...);方法给父类提供子类的this值来实现*/
    

    3.多态
    一个接口,多种方式。

       function getName(person) {
            person.name();
        }
        var tang = function () { }
        tang.prototype.name = function () {
            console.log("我是唐三")
        }
        var wu = function () { }
        wu.prototype.name = function () {
            console.log("我是小舞")
        }
        var rong = function () { }
        rong.prototype.name = function () {
            console.log("我是荣荣")
        }
        getName(new tang())
        getName(new wu())
       /*ps:多态是面向对象的特点,目的是为了让程序更方便,不必太局限于此示例*/
    

    javascript中的原型?

    在javascript中,函数可以有属性。 每个函数都有一个特殊的属性叫作原型(prototype)。

    //例:
     
     function User(name) {
            this.name = name
       }
     console.log(User.prototype)
    
    //上面定义了一个User函数,运行后我们得到了其原型对象。
    
    {
    constructor:ƒ User(name, pass) ,
    __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
    }
    

    我们在User的原型上添加输出名字的方法

       function User(name) {
            this.name = name
        }
        User.prototype.getUsername =function(){
            console.log(this.name);
        }
       console.log(User.prototype)
    
        //现在看看User函数的原型变化。
    
      {
    constructor:ƒ User(name, pass),
    getUsername:ƒ (),
    __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
    }
    

    然后,我们可以使用 new 运算符来在现在的这个原型基础之上,创建一个 User 的实例,得到一个实例对象。

     function User(name) {
            this.name = name
        }
        User.prototype.getUsername =function(){
            console.log(this.name);
        }
      var onUser=new User()
      console.log(onUser);
    
      //现在看看onUser的实例对象。
    
    {
        name:'张三',
        __proto__: {
          constructor:ƒ User(name, pass),
          getUsername:ƒ (),
          __proto__: {
            constructor: ƒ Object(),
            hasOwnProperty: ƒ hasOwnProperty(),
            isPrototypeOf: ƒ isPrototypeOf(),
            propertyIsEnumerable: ƒ propertyIsEnumerable(),
            toLocaleString: ƒ toLocaleString(),
            toString: ƒ toString(),
            valueOf: ƒ valueOf()
        }
        }
    }
    
    

    仔细对比会发现onUser实例对象会有一个(proto )私有属性,并且指向User构造函数的原型。

       function User(name) {
            this.name = name
        }
        User.prototype.getUsername =function(){
            console.log(this.name)
        }
        var onuser=new User('张三')
        console.log(onUser.__proto__===User.prototype)
        //true
    

    什么是原型链?

    上面我们说到,函数的prototype属性即为原型,并且可以在原型上添加属性或者方法。仔细查看prototype会发现,每个构造函数的原型对象(prototype)上也会有一个自己的隐式原型对象 ( proto ) ,proto 上还有proto 直到原型对象为null,这种关系称为原型链。

    希望对学习的小伙伴有帮助。谢点赞~~转请注明链接


    1. 向上滚动鼠标至段落头

    相关文章

      网友评论

          本文标题:1.web前端基础储备之—js的面向对象风格以及原型和原型链

          本文链接:https://www.haomeiwen.com/subject/oerroktx.html