1. 程式人生 > 程式設計 >一起來了解JavaScript面向物件

一起來了解JavaScript面向物件

目錄
  • 原型鏈
  • Object的原型
    • 頂層原型
    • 建立Object物件的記憶體圖
  • Object是所有類的父類
    • 原型鏈實現繼承
      • 借用建構函式實現繼承
        • 總結

          Script原型鏈

          每一個物件都有原型,指向另一個物件,另一個物件也有自己的原型,就這樣由原型的原型構成的鏈條就叫原型鏈。

          image-20210924092335152

          原型鏈的盡頭

          如果一個原型鏈是,沒用盡頭的,那麼在查詢一原型鏈上不存在的屬性時,就會一直查詢下去,存在死迴圈了。顯然不是這樣的,那麼原型鏈的盡頭是什麼?

          Object的原型

          頂層原型

          看程式碼~

          // obj字面量建立方法類似於 new Object()
          // 那麼 obj物件就是Object的一個例項,也就是說obj.__proto__ === Object.prototype
          var obj = {
            name: "fzb",};
          // 那麼obj.__proto__ 或者 Oject.prototype 的__proto__ 是什麼? 答案是: null
          console.log(obj.__proto__); // [Object: null prototype] {}
          console.log(obj.__proto__.__proto__); // null
          

          [Object: null prototype] {}的特殊之處:

          1、該物件存在原型屬性,只是原型指向了null,就是已經是頂層原型了。

          2、該物件上還存在許多其他的方法,只是不可列舉,看不到。

          建立Object物件的記憶體圖

          image-20210924094822274

          上方例子的記憶體圖

          image-20210924095218150

          Object是所有類的父類

          原型鏈最頂層的原型物件就是Object的原型物件

          例子:

          function Student(sno,name) {
            this.sno = sno;
            this.name = name;
          }
          const stu = new Student(201801,"fzb");
          
          console.log(stu); // Student { sno: 201801,name: 'fzb' }
          console.log(stu.__proto__); // {}
          console.log(stu.__proto__.__proto__); // [Object: null prototype] {}
          
          console.log(Student.__proto__); // {}
          /* ***************後面將具體講解註釋內容***************
           * 為什麼不是 Student.__proto__ = [Object: null prototype] {}
           * 是因為 Student.__proto__ = Function.prototype 
           * Function.prototype.__proto__ = Object.prototype = [Object: null prototype] {}
           * ***************後面將具體講解註釋內容***************
           */
          console.log(Student.__proto__.__proto__); // [Object: null prototype] {}
          
          

          記憶體圖:

          image-20210924101359674

          原型鏈實現繼承

          繼承可以重複利用程式碼,子類可以使用

          例子:

          function Person() {
            this.name = "fzb";
          }
          
          Person.prototype.running = function () {
            console.log(this.name + "正在跑步~");
          };
          
          function Student(sno) {
            this.sno = sno;
          }
          Student.prototype = new Person();
          // 重寫整個原型物件之後,要重新配置 constructor
          Object.defineProperty(Student.prototype,"constructor",{
            configurable: true,enumerable: false,writable: true,value: Student,});
          Student.prototype.studying = function () {
            console.log(this.name + "正在學習");
          };
          
          const stu = new Student(201801);
          stu.running(); // fzb正在跑步~
          stu.studying(); // fzb正在學習
          

          記憶體圖:

          image-20210924105330732

          缺陷

          1> 在列印子類物件時,有些屬性本應該打印出來的,但是因為在父類上,無法打印出來。

          2> 多個子類物件在進行某些操作時,會出現相互影響。

          // 在上方例子上,加一點點程式碼,
          function Person() {
            this.name = "fzb";
            this.friends = []; // 增加一個屬性
          }
          const stu1 = new Student(201801);
          stu1.friends.push("zzw");
          const stu2 = new Student(201801);
          console.www.cppcns.comlog(stu2.friends); // [ 'zzw' ]
          // stu2上取到了stu1的friends屬性,這是不可以的
          

          3> 無法傳遞引數,有些屬性存在父類建構函式內,子類例項化時,初始化引數無法傳入到父類。

          借用建構函式實現繼承

          在子類建構函式內,呼叫建構函式。使改變父類建構函式內的this指向,然後父類在this上新增的屬性就會在子類例項化的物件上。

          function Person(name) {
            this.name = name;
            this.friends = [];
          }
          
          Person.prototype.running = function () {
            console.log(this.name + "正在跑步~");
          };
          
          function Student(sno,name) {
            Person.call(this,name); // 新增程式碼
            this.http://www.cppcns.comsno = sno;
          }
          Student.prototype = new Person();
          // 重寫整個原型物件之後,要重新配置 constructor
          Object.defineProperty(Student.prototype,});
          Student.prototype.studying = function () {
            console.log(this.name + "正在學習");
          };
          
          const stu1 = new Student(201801,"stu1");
          stu1客棧.friends.push("zzw");
          const stu2 = new Student(201802,"stu2");
          console.log(stu2.friends); // []
          

          這時原型鏈實現繼承的三個弊端,就解決的。但是又出現了新的缺陷。

          缺陷

          1> 父類建構函式至少執行了兩次以上

          2> 子類建構函式的原型物件是父類的例項物件,那麼個物件上的屬性將會是undefined

          image-20210924111324798

          總結

          本篇文章就到這裡了,希望能夠給你帶來幫助,也希望您能夠多多關注我們的更多內容!