鍍金池/ 問答/Java  網(wǎng)絡(luò)安全  HTML/ javascript es6 super 不理解

javascript es6 super 不理解

本人新手, 最近在看阮一峰老師的es6里面class的繼承這一章, 對super一些概念不理解, 具體如下:
在阮一峰老師的博客里有這樣一段代碼:

class A {
  constructor() {
    this.x = 1;
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
    super.x = 3;
    console.log(this.x); // 3
  }
}

let b = new B();

阮一峰老師是這么說的

由于this指向子類實例,所以如果通過super對某個屬性賦值,這時super就是this,賦值的屬性會變成子類實例的屬性。
上面代碼中,super.x賦值為3,這時等同于對this.x賦值為3

這里我很不理解, 為什么使用super.x進(jìn)行賦值以后就等同于this.x,

我的理解是:
根據(jù)阮一峰老師前面說的

super作為對象時,在普通方法中,指向父類的原型對象

那么這里的super.x = 3實際上應(yīng)該就是A.prototype.x = 3, 那么對于子類B應(yīng)該是沒有影響的, 所以個人理解結(jié)果應(yīng)該是2
但是瀏覽器跑出來的結(jié)果卻和阮老師的結(jié)果一樣是3, 所以請問應(yīng)該如何理解

希望能有前輩給一個清晰的解答, 謝謝了!

回答
編輯回答
刮刮樂
如果通過super對某個屬性賦值,這時super就是this

這樣看的話就好理解了啊,在對super進(jìn)行某個屬性賦值時,這個時候 super 就是 this,在別的時候,super 指向的應(yīng)該是父類,這樣就可以解釋了。

2017年6月7日 16:07
編輯回答
涼薄
由于this指向子類實例,所以如果通過super對某個屬性賦值,這時super就是this,賦值的屬性會變成子類實例的屬性。
上面代碼中,super.x賦值為3,這時等同于對this.x賦值為3
class A {
  constructor() {
    this.x = 1;
  }
}

class B extends A {
  constructor() {
    super();
    this.x = 2;
    console.log(super.x)// 如果上述成立 那么super.x=2 但是結(jié)果是undefined
    super.x = 3;
    console.log(this.x); // 3
  }
}

let b = new B();

我并不理解super的具體實現(xiàn),但是按照這邏輯加了一句代碼,結(jié)果顯然是不成立。弱弱的懷疑一下這不是通過現(xiàn)象反猜的吧?

2017年2月23日 05:56
編輯回答
你的瞳

super()并不是通過prototype實現(xiàn)繼承的,而是類似于傳統(tǒng)的class方式來實現(xiàn)。也就是子類不能修改父類的屬性。我猜想,當(dāng) super.x = 3 時,會將3賦值給this,然后刪除了super.x。由此無法反向給父類賦值

2017年9月6日 13:06
編輯回答
玩控

前幾天剛好在學(xué)習(xí)這個,看到文檔里得出3我也很疑惑,自己運行了一下發(fā)現(xiàn)是等于2的,難道只有我一個人得出了2?

class A {
  constructor() {                             // constructor方法默認(rèn)返回實例對象(即this)
    this.x = 1;                               // 父類的實例屬性
    console.log('子類B的實例:', this);        // B?{x: 1},執(zhí)行兩次,因為下面執(zhí)行了super()兩次,返回的是子類B的實例。
  }
  foo() {
    return 10;
  }
}
console.log('父類的原型對象:', A.prototype);  // {constructor: ?, foo: ?}。類的所有方法都定義在類的prototype屬性上面。

class B extends A {
  constructor() {
    super();                                  // 2. super使用的第一種情況,super作為函數(shù)調(diào)用時,雖然代表了父類A的構(gòu)造函數(shù),但是返回的是子類B的實例。
    console.log(super() === this);            // 3. super返回的是子類的實例對象,this代表子類的實例對象,所以判斷它們相等返回true。
    this.x = 2;                               // 1. this代表實例對象,就是下面new出來的實例對象b。(按照123的順序理解)
    console.log('=====驗證=====', this);      // B?{x: 2}

    // 題主主要問的是super當(dāng)做對象使用時的情況,super作為對象時,在普通方法中,指向父類的原型對象。
    console.log(super.foo());                 // 10,相當(dāng)于A.prototype.foo()
    // 由于super指向父類的原型對象,所以定義在父類實例上的方法或?qū)傩裕ㄒ簿褪歉割愔械膖his.x = 1),是無法通過super調(diào)用的。
    console.log(super.x);                     // undefined,實際讀取的是A.prototype.x,所以返回undefined。                     
    Object.defineProperty(A.prototype, 'x', { // 這里難道不是說明,執(zhí)行super.x = 3;的時候,實際就是執(zhí)行的A.prototype.x。
      set(val) {
        console.log(val)                      // 先輸出'測試',后輸出3。如果不是執(zhí)行的A.prototype.x,就不會進(jìn)到這里,不會有輸出。
      }
    });
    super.x = '測試';
    super.x = 3;
    console.log('最終結(jié)果', this.x);          // 最終結(jié)果 2
  }
}
let b = new B();
console.log('=====驗證=====', b);            // B?{x: 2}

控制臺:
圖片描述

個人理解和題主一樣,super指向的就是父類的原型對象,所以在super.x上賦值,不會影響到指向?qū)嵗龑ο蟮膖his,所以應(yīng)該還是2,實際運行結(jié)果也是2。
為什么有人得到2有人得到3,可能是es版本的原因,具體還需仔細(xì)研究,希望明白的大神不吝賜教。

2018年8月13日 06:06
編輯回答
冷咖啡

調(diào)用super() 時會在類中生成一個新的上下文this, 所以阮說給super賦值,就是賦值給this,實際開發(fā)中并不應(yīng)該給super賦值,super 關(guān)鍵字用于調(diào)用對象的父對象上的函數(shù)。

2018年1月5日 23:00
編輯回答
吢涼

題主看書看仔細(xì)些

第二種情況,super作為對象時,在普通方法中,指向父類的原型對象;在靜態(tài)方法中,指向父類。
ES6 規(guī)定,在子類普通方法中通過super調(diào)用父類的方法時,方法內(nèi)部的this指向當(dāng)前的子類實例。

這兩句話連在一起,不矛盾!意思就是:

意思是:

在子類普通方法中通過super調(diào)用父類的方法時

super指向父類的原型對象,但是父類的方法中的this指向當(dāng)前的子類實例。

super.x = 3;

這里super指向父類的原型對象,沒錯!

但是底層并不是直接執(zhí)行

A.prototype.x = 3

而是轉(zhuǎn)換了底層的this,最終效果類似于:

this = 3

代碼驗證:

class A {
  constructor() {
    this.x = 1
  }
}

class B extends A {
  constructor() {
    super()
    this.x = 2
    Object.defineProperty(A.prototype, 'x', {
      set: function(val) {
        console.log(this, val)
         //B {x: 2} 3,證明對super的賦值最終作用到了B {x: 2}身上,也就是新生成的實例,this
      }
    })
    super.x = 3
    console.log(this.x) // 3
  }
}

let b = new B()

你再看看阮老師舉的函數(shù)調(diào)用的例子,這個例子就更清楚了,因為函數(shù)可以用 call

clipboard.png

代碼:

class A {
  constructor() {
    this.x = 1
  }
  print() {
    console.log(this.x)
  }
}

class B extends A {
  constructor() {
    super()
    this.x = 2
  }
  m() {
    // super.print()//上下兩句等價的,所以上面這句隱含轉(zhuǎn)換了this
    super.print.call(this)
  }
}

let b = new B()
b.m() // 2

super.print() 等價于super.print.call(this),因為底層隱含轉(zhuǎn)換了this

所以,最終有了下面的解釋:

由于this指向子類實例,所以如果通過super對某個屬性賦值,這時super就是this,賦值的屬性會變成子類實例的屬性。
2018年5月19日 05:53