質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Q&A

解決済

3回答

3063閲覧

拡張したjQueryインスタンスをDOMツリーに追加して、再度取得後も拡張を維持する方法

mitsuru793

総合スコア157

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

0グッド

0クリップ

投稿2015/08/24 16:12

編集2015/08/25 12:00

下記のようにDOMツリーから要素を取得した場合は、拡張したメソッドがundefinedになってしまいます。これはjQueryのコンストラクタで再度i要素が初期化されてしまうことはわかります。

ですが、DOMツリーに追加してから、再度取得後も拡張メソッドを維持するようにしたいです。

javascript

1// 拡張したjQueryオブジェクトをDOMツリーに追加 2$i = $('<i>').extend({ 3 hello: function() { 4 console.log("hello from extend-add"); 5 } 6}); 7$('div#stage').append($i); 8 9// DOMツリーから取得すると元のjQueryオブジェクトに戻ってしまう 10$gotI = $('div#stage').find('i'); 11$gotI.hello() // undefined

$.fn.extendを使用すれば可能かもしれませんが、これだと全ての生成したjQueryオブジェクトに影響してしまいます。今回はjQueryのインスタンスメソッドをオーバーライドしたいため、$(element)で生成した要素のみに独自メソッドを定義したいです。

何か良い方法はないでしょうか?
ご回答、よろしくお願致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

KiKiKi_KiKiさんの回答へのコメントにて既にお気づきの様子ですが、jQuery から prototype 継承したカスタムコンストラクタを作成すれば、任意のメソッドを追加できます。
下記コードは jquery-2.1.4.js を参考にしたコードです。

HTML

1<script src="jquery-2.1.4.js"></script> 2<script> 3function customizedQuery (selector, context) { 4 return new customizedQuery.fn.init(selector, context); 5} 6 7Object.keys(jQuery).forEach(function (key) { 8 customizedQuery[key] = jQuery[key]; 9}); 10 11customizedQuery.prototype = jQuery.fn; 12customizedQuery.fn.hello = function hello () { 13 console.log(this.data('hello')); 14}; 15 16customizedQuery('<span data-hello="Hello, World!">').hello(); // "Hello, World!" 17</script>

ES5 のコードで書いている為、IE8- の ES3 前提のコードをお望みの場合は適宜書き換えてください。

  • Array.prototype.forEachfor 文に変更
  • Object.keysfor-in + Object.prototype.hasOwnProperty に変更

投稿2015/08/25 13:30

think49

総合スコア18156

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mitsuru793

2015/08/26 19:12

現在jQueryのコンストラクタについて勉強中です。 customezedQuery定義してから、jQueryのプロパティの参照をcustomizedQueryにコピーするのですね。 ソースコードまで掲示していただき、ありがとうございます。
guest

0

ベストアンサー

fumokmmさんの書かれているdata()を使う方法が良いと思います!

1点だけ

javascript

1$('div#stage').append($i);

とあるので、var $i = $('i')この部分は元々HTML上にある<i>を取得しているのではなく、新しく作り出していると言うことであれば、var $i = $('<i>')の書き間違いではないでしょうか?

もし"i"という文字列でと言うことであれば、
$iにはdataをつけることができません。そして、$gotI = $('div#stage').find('i');はそもそも別のものを取得しようとしていることになるので、hello()は実行できないので注意が必要かと思います。

javascript

1ocnsole.log( $i.data('hello') ); // undefined 2ocnsole.log( $i.data() ); // undefined -> dataをつけることができない。 3ocnsole.log( $gotI.data('hello') ); // undefined ※そもそも$iとは別のものを選択しているので...

また、$('<i>')で新しくタグを作る場合も、元々<div id="stage">の中に<i>があるような場合は注意が必要です。

javascript

1$i = $('<i>').data('hello', function() { 2 console.log("hello from extend-add"); 3 }); 4 $('div#stage').append($i); 5 6 $gotI = $('div#stage').find('i'); 7 $gotI.each(function(i, elm) { 8 var $i = $(elm); 9 console.log($i, $i.data('hello')); 10 // -> [i, context: i] undefined 11 // -> [i, context: i] function anonymous( 12 }); 13 $gotI.data('hello')(); // 元々あった i には hello()が無いのでエラーになる

おまけ

$gotI.hello();がundefinedになってしまう原因は、
メソッドが<i>に付いているのではなく、$iというjQueryオブジェクトの方に付いているので、
$i$gotIとは別のjQueryオブジェクトなので、$gotI.helloにはってプロパティは無いよ!となっているためです。
console.log()でオブジェクトを見比べてみると判ると思います。

// console.log($i); [prevObject: n.fn.init[1], context: document, selector: "i"] context: document hello: function() // hello がある length: 0 prevObject: n.fn.init[1] __proto__: n[0] selector: "i" // console.log($gotI); [prevObject: n.fn.init[1], context: document, selector: "div#stage i"] context: document length: 0 prevObject: n.fn.init[1] selector: "div#stage i" __proto__: n[0]

$(element)[0]、または$(element).get(0)でelementを取ってきてelementにメソッドをつける方法もありますが、あまりオススメはしないので参考程度に。

javascript

1$(function() { 2 var $i = $('<i>'); 3 $('div#stage').append($i); 4 $i.get(0).hello = function() { 5 console.log("hello"); 6 }; 7 8 var $gotI = $('div#stage').find('i'); 9 $gotI[0].hello(); 10});

投稿2015/08/25 04:07

KiKiKi_KiKi

総合スコア596

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mitsuru793

2015/08/25 12:13

$('i')については私の書き間違えでした。$('<i>')で合っています。 お手数おかけし、申し訳ございません。 dataを使うと、要素を再取得時にdataを再度使う必要が出てきます。 しかし、KiKiKi_KiKiさんが最後の示してくれた要素取得後にメソッドを追加したらその必要がなくなりますね。 取得してその要素のメソッドを追加する、jQueryのようなコンストラクタを作るの1つの手だなと思いました。 ご回答頂き、ありがとうございます。
guest

0

dataを使えば同じようなことができそうです。

javascript

1 $(function(){ 2 // 拡張したjQueryオブジェクトをDOMツリーに追加 3 $i = $('i').data('hello', function() { 4 console.log("hello from extend-add"); 5 }); 6 $('div#stage').append($i); 7 8 // DOMツリーから取得すると元のjQueryオブジェクトに戻ってしまう 9 $gotI = $('div#stage').find('i'); 10 $gotI.data().hello(); // dataに格納して追加したfunctionはアクセス可能 11 });

追加したメソッドへのアクセスに.data()を挟むのでちょっと不便ですが、ご参考までに。

投稿2015/08/24 22:05

fumokmm

総合スコア19

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mitsuru793

2015/08/25 00:36

dataメソッドは関数も入れることができるのですね。参考にさせて頂きます。 ご回答、ありがとうございます。
KiKiKi_KiKi

2015/08/25 04:08

$gotI.data('hello')(); という書き方でも実行できますよ
mitsuru793

2015/08/25 11:59

function hell() {}がそのまま入っているので、()をつければ関数呼び出しになりますよね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問