簡體   English   中英

擴展本機對象的工廠/類

[英]Factory/class that extends native object

我正在嘗試擴展內置Map對象。 這是起作用的部分:

 var Attributes = class extends Map { get text () { let out = []; for ( let [ k, v ] of this.entries() ) { out.push( k + '="' + v + '"' ); } return out.join( ' ' ); } // simplified for brevity! set text ( raw ) { this.clear(); var m, r = /(\\w+)="([^"]+)"/g; while ( ( m = r.exec( raw ) ) ) { this.set( m[1], m[2] ); } } }; var a = new Attributes(); a.text = 'id="first"'; console.log( a.get( 'id' ) ); // first a.set( 'id', 'second' ); console.log( a.text ); // id="second" 

但是我想將該類無縫集成到我的庫中,而是公開一個工廠方法,該方法有雙重作用,用作構造函數。 用戶不需要知道這種特殊方法是不尋常的。 這只會使事情復雜化。 但是,我自己的代碼需要能夠使用instanceof進行輸入驗證。 這就是我要的:

 var obj = {}; obj.attr = function ( text ) { if ( new.target ) { this.text = text; } else { return new obj.attr( text ); } }; console.log( obj.attr() instanceof obj.attr ); // true 

以上也是可行的。 但是,無論我如何嘗試將兩種方法結合起來,Chrome和Firefox都會拋出各種錯誤。 下面的代碼例如拋出TypeError“ this.entries(...)[Symbol.iterator]不是函數”:

 var obj = {}; obj.attr = function ( text ) { if ( new.target ) { this.text = text; } else { return new obj.attr( text ); } }; obj.attr.prototype = Object.assign( new Map(), { get text () { let out = []; for ( let [ k, v ] of this.entries() ) { out.push( k + '="' + v + '"' ); } return out.join( ' ' ); }, // simplified for brevity! set text ( raw ) { this.clear(); var m, r = /(\\w+)="([^"]+)"/g; while ( ( m = r.exec( raw ) ) ) { this.set( m[1], m[2] ); } } } ); 

我在這里想念和/或誤解了什么?

更新:這有可能使用Object.setPrototypeOf()但性能損失可能會非常大。 可以使用Reflect.construct() 盡管這與Object.setPrototypeOf()到底有什么不同,但對我來說並不明顯。 Reflect似乎通常很慢,因為顯然當前沒有瀏覽器對其進行優化。

 var Attributes = class extends Map { constructor ( text ) { super(); this.text = text; } get text () { let out = []; for ( let [ k, v ] of this.entries() ) { out.push( k + '="' + v + '"' ); } return out.join( ' ' ); } // simplified for brevity! set text ( raw ) { this.clear(); if ( !raw ) return; var m, r = /(\\w+)="([^"]+)"/g; while ( ( m = r.exec( raw ) ) ) { this.set( m[1], m[2] ); } } }; var obj = {}; obj.attr = function ( text ) { if ( new.target ) { return Reflect.construct( Attributes, [ text ], obj.attr ); } else { return new obj.attr( text ); } }; obj.attr.prototype = Object.create( Attributes.prototype ); console.log( obj.attr() instanceof obj.attr ); console.log( obj.attr() instanceof Attributes ); console.log( obj.attr() instanceof Map ); var a = obj.attr(); a.text = 'id="first"'; console.log( a.get( 'id' ) ); a.set( 'id', 'second' ); console.log( a.text ); 

它不起作用,因為Object.assign不會復制getter / setter,而是對其進行調用。 因此,將getter(獲取文本)與window一起調用, 顯然會失敗:

MDN:

Object.assign()方法僅將可枚舉和自己的屬性從源對象復制到目標對象。 它在源上使用[[Get]],在目標上使用[[Set]],因此它將調用getter和setter。 如果合並源包含getter,則可能不適合將新屬性合並到原型中。 要將屬性定義(包括其可枚舉性)復制到原型中,應改用Object.getOwnPropertyDescriptor()和Object.defineProperty()。

要將對象復制到地圖中而不丟失設置者,可以這樣做:

obj.attr.prototype = new Map();
var settings = {
  get text(){},
  set text(v){}
};

for(key in settings){
  Object.defineProperty(
    obj.attr.prototype,
    key,
    Object.getOwnPropertyDescriptor(settings,key)
  );
}

但是,這仍然會失敗。 地圖與對象不同。 調用this.clear()會崩潰,因為它期望是一個映射而不是常規對象。 因此,還有兩個選擇:

1)使用類語法和工廠:

 {
  let internal = class extends Map {
   constructor(text){
     super();
     this.text = text;
   };
   set text(v){};
   get text(){};
  };

  var obj = {
   attr(text){
     return new internal(text);
    }
  };
}

2)內部保留地圖:

 obj.attr = function(text){
   if(this === window) return new obj.attr(text);
   this.map = new Map();
   this.text = text;
};
obj.attr.prototype = {
  set text(v){
   this.map.set("text",v);
  },
  get text(){
   return this.map.get("text");
  }
};

“類擴展價值#<object> 不是構造函數或 null"<div id="text_translate"><p> 感謝閱讀我的帖子 我的代碼出現了這個錯誤:“Class extends value # is not a constructor or null” 這是我的代碼,我正在嘗試導出/導入類。</p><p> 怪物.js:</p><pre> const miniMonster = require("./minimonster.js"); class monster { constructor(options = { name }, health) { this.options = options; this.health = 100; this.heal = () => { return (this.health += 10); }; } } let bigMonster = new monster("Godzilla"); console.log(bigMonster); console.log(bigMonster.heal()); let mini = new miniMonster("Demon"); console.log(mini); console.log(mini.heal()); module.exports = monster;</pre><p> 迷你怪物.js:</p><pre> const monster = require("./monster.js"); class miniMonster extends monster { constructor(options) { super(options); this.health = 50; this.heal = () => { return (this.health += 5); }; } } let miniM = new miniMonster("Jon"); console.log(miniM); module.exports = miniMonster;</pre><p> 感謝您提供的任何幫助,</p><p> 祝你有美好的一天</p></div></object>

[英]"Class extends value #<Object> is not a constructor or null"

類型錯誤:Class 擴展值 #<object> 不是反應js中的構造函數或null<div id="text_translate"><p> 我試圖超越一些主要反應按鈕組件的 function,但是在擴展主要反應按鈕組件 class 時出現此錯誤。 這是我的代碼:</p><pre> import { Button } from "primereact/button"; class BtnBox extends Button { constructor(props) { super(props); this.renderLabel = this.renderLabel.bind(this); } renderLabel() { return &lt;span&gt;icon&lt;/span&gt;; } } class IconButton extends React.Component { render() { return ( &lt;div className="icon-button"&gt; &lt;BtnBox {...this.props} /&gt; &lt;/div&gt; ); } } export default IconButton;</pre></div></object>

[英]TypeError: Class extends value #<Object> is not a constructor or null in react js

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

相關問題 在工廠使用擴展 function 而不是 class `extends` 如何在ES6中使用類擴展對象? “類擴展價值#<object> 不是構造函數或 null"<div id="text_translate"><p> 感謝閱讀我的帖子 我的代碼出現了這個錯誤:“Class extends value # is not a constructor or null” 這是我的代碼,我正在嘗試導出/導入類。</p><p> 怪物.js:</p><pre> const miniMonster = require("./minimonster.js"); class monster { constructor(options = { name }, health) { this.options = options; this.health = 100; this.heal = () => { return (this.health += 10); }; } } let bigMonster = new monster("Godzilla"); console.log(bigMonster); console.log(bigMonster.heal()); let mini = new miniMonster("Demon"); console.log(mini); console.log(mini.heal()); module.exports = monster;</pre><p> 迷你怪物.js:</p><pre> const monster = require("./monster.js"); class miniMonster extends monster { constructor(options) { super(options); this.health = 50; this.heal = () => { return (this.health += 5); }; } } let miniM = new miniMonster("Jon"); console.log(miniM); module.exports = miniMonster;</pre><p> 感謝您提供的任何幫助,</p><p> 祝你有美好的一天</p></div></object> 在擴展本機類的ScalaJS類中調用重載的超級構造函數 class X 和 class X 擴展 Object 之間的區別是什么? 未捕獲的類型錯誤:類擴展值 #<Object> 不是構造函數或 null 類型錯誤:Class 擴展值 #<object> 不是反應js中的構造函數或null<div id="text_translate"><p> 我試圖超越一些主要反應按鈕組件的 function,但是在擴展主要反應按鈕組件 class 時出現此錯誤。 這是我的代碼:</p><pre> import { Button } from "primereact/button"; class BtnBox extends Button { constructor(props) { super(props); this.renderLabel = this.renderLabel.bind(this); } renderLabel() { return &lt;span&gt;icon&lt;/span&gt;; } } class IconButton extends React.Component { render() { return ( &lt;div className="icon-button"&gt; &lt;BtnBox {...this.props} /&gt; &lt;/div&gt; ); } } export default IconButton;</pre></div></object> 為什么在javascript過濾中擴展數組的類的對象會調用它的構造函數? CoffeeScript類擴展-TypeError:對象# <Google> 沒有方法“執行” WebdriverIO自定義報告程序-TypeError:類擴展值# <Object> 不是構造函數或null
 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM