2

プロトタイプを失うことなく要素を返す関数を作成する方法を知っている人はいますか? 新しい要素を作成し、それを要素として返す関数を作成しようとしています。この関数には、その要素を操作するメソッドがあります。その要素を返すと、プロトタイプは機能しません。その関数で使用しない場合return、プロトタイプは正常に動作しますが、関数はthisオブジェクトを返します。このコードを見てください:

function ObjEl(tagName, id) {
    'use strict';
    this.node = document.createElement(tagName);
    if (typeof id === 'string' && id.match(/^[a-zA-Z\d\_\-]+$/)) {
        this.node.setAttribute('id', id);
    }

    // return this.node;
}

ObjEl.prototype.atr = function (key, val) {
    'use strict';
    this.node.setAttribute(key, val);
    return this;
};

のコメントを外すreturn this.node;と、呼び出しtest = ObjEl('div', 'test');たときに が返さ<div id="test"></div>れますが、このコードは機能しません。

test = ObjEl('div', 'test').remove();
4

2 に答える 2

0

可能なオプション

JavaScript でこの種の動作を実現するための 2 つの最良の方法 (私が知っている)は、問題の要素の処理を内部で管理するラッピング オブジェクトを作成することです。または、各要素のDOMノードを目的のエクストラで直接拡張します。例えば:

var extend = function( elm ){
  elm.attr = extend.attr;
};
extend.attr = function(){
  // your code here
};
var elm = extend(document.getElementById('div'));

特定の要素のソース コンストラクター、つまりHTMLElementのプロトタイプに追加することもできますが、これはクロスブラウザーでは機能せず、他のコードで問題が発生する可能性があります。基本コンストラクターをいじることは一般的に嫌われています。

私が選んだ方法

過去に、次のラフなスニペットを使用して、多数の異なるインターフェイスを選択的に組み合わせて同じオブジェクトにまとめました。ただし、これは経験豊富なコードではなく、基本的にクロージャーの単なるバンドルであるため、メモリ リークのリスクを回避するために、適切なセットアップと破棄の管理から大きな恩恵を受ける可能性があります。

var harmony = function(){
  if( !(this instanceof harmony) ) { return new harmony(); }
};
harmony.prototype.borrow = function( owner, descriptor ){
  var i, dlen = descriptor.length, item;
  for ( i=0; i<dlen; i++ ) {
    if ( (item = owner[descriptor[i]]) && item.apply ){
      this.borrowMethod( owner, descriptor[i] );
    }
    else {
      this.borrowAttribute( owner, descriptor[i] );
    }
  }
  return this;
};
harmony.prototype.add = function( owner, methods ){
  for ( var i in methods ) { this.addMethod( owner, i, methods[i] ); }
  return this;
};
harmony.prototype.addMethod = function( owner, name, method ){
  this[name] = function(){ return method.apply( owner, arguments ); };
  return this;
};
harmony.prototype.borrowMethod = function( owner, name ){
  this[name] = function(){ return owner[name].apply( owner, arguments ); };
  return this;
};
harmony.prototype.borrowAttribute = function( owner, attributeName ){
  var self = this; self[attributeName] = function(){
    if ( arguments.length ) { owner[attributeName] = arguments[0]; return self; }
    return owner[attributeName];
  };
  return self;
};

使用法

上記を使用して要素をラップし、ネイティブ オブジェクトからメソッドを借用し、独自のメソッドで拡張できます。これが私の言いたいことの大まかな考えです。これは決して最終的なコードではありません。

var ElementHarmony = function(elm){
  var self = harmony()
    .borrow( elm, ['innerHTML', 'getElementsByTagName'] )
    .add( elm, {
      getElement: function(){
        return elm;
      },
      attr: function( name, value ){
        if ( arguments.length > 1 ) {
          this.setAttribute( name, value );
          return self;
        }
        else {
          return this.getAttribute( name );
        }
      }
    })
  ;
  return self;
}
/// create our example element and wrap with a harmony instance
var elm = ElementHarmony(document.createElement('span'))
  .innerHTML('<b>hello</b>')
  .attr('style', 'border: 1px solid red')
;
/// find the bold tag inside, and modify it's style
var bold = ElementHarmony(elm.getElementsByTagName('b')[0])
  .attr('style', 'background: orange')
;
/// use getElement() to get back to the original element,
/// when passing to native methods.
(document.body||document.documentElement).appendChild(elm.getElement());

ハーモニー オブジェクトを使用すると、所有者オブジェクトからメソッドと属性の両方を借用できますが、属性はメソッドに変換されますinnerHTML()。コードが最新のブラウザーでのみ実行されることがわかっている場合は、この動作を変更してゲッターとセッターを利用することができますが、それはまた別の話です。

ヘイディドルディドル

これがフィドルです。

http://jsfiddle.net/K2Xux/

于 2013-11-03T23:35:38.273 に答える