著作一覧 |
function false_check(x) { if (x) { alert('true'); } else { alert('false'); } } false_check(false); false_check(0); false_check(Number(0)); false_check(new Number(0)); var x; false_check(x); false_check(Boolean(false)); false_check(new Boolean(false)); false_check(Boolean(new Boolean(false)));
function substr(s) { try { alert(s.substring(0, 2)); } catch (e) { alert(e); } } StringX = function(x) { this.value = x; } StringX.prototype = "abcdef"; StringY = function(x) { this.value = x; } StringY.prototype = new String("abcdef"); var x = new StringX("abcdef"); var y = new StringY("abcdef"); substr(x); substr(y);
alert('abc'); alert(new String('abc')); alert('abc'[0]); alert(new String('abc')[0]);(追加:IE7とFirefoxでは表示が異なる。どちらがECMAScriptの仕様に合致するか答えよ)
var x = [1,2,3,4,5] var y = x.concat([6]); x[0] = 8; alert(y); x = [1,2,3,4,5] y = x.reverse(); x[0] = 8; alert(y); x = [1,2,3,4,5] y = x.push(6); alert(y);
function eval_result(x) { try { alert(eval(x)); } catch (e) { alert(e); } } eval_result('a'); eval_result("32 +"); eval_result(32); eval_result(1, 3); eval_result(["e", "v", "a", "l"]); var s = "eval_result(s)"; eval_result(s); var x = "eval_result(x)"; eval_result(x); eval_result("eval_result(1)");
Test = function(x) { this.value = x; } Test.prototype.get = function() { return this.value; } XTest = function(y) { Test(y); } XTest.prototype = new Test(0); var x = new XTest(3); alert(x.get()); Test.prototype.sub = function(x) { return this.value - x; } alert(x.sub(30)); Test2 = function(x) { this.value = x; } Test2.prototype.get = function() { return this.value; } XTest2 = function(y) { Test2(y); } XTest2.prototype = Test2.prototype; var x = new XTest2(3); alert(x.get()); Test2.prototype.sub = function(x) { return this.value - x; } alert(x.sub(30));
Test = function(x) { this.value = x; } Test.prototype.get = function() { return this.value; } XTest = function(y) { this.value = y; } XTest.prototype = new Test(0); var x = new XTest(3); alert(x.get()); Test.prototype.sub = function(x) { return this.value - x; } alert(x.sub(30)); Test2 = function(x) { this.value = x; } Test2.prototype.get = function() { return this.value; } XTest2 = function(y) { this.value = y; } XTest2.prototype = Test2.prototype; var x = new XTest2(3); alert(x.get()); Test2.prototype.sub = function(x) { return this.value - x; } alert(x.sub(30));
Test = function(x) { this.value = x; } Test.prototype.get = function() { return this.value; } XTest = function(y) { this.value = y; } XTest.prototype = new Test(0); var x = new XTest(3); alert(x.get()); XTest.prototype.sub = function(x) { return this.value - x; } alert(x.sub(30)); var x = new Test(3); alert(x.sub(30)); Test2 = function(x) { this.value = x; } Test2.prototype.get = function() { return this.value; } XTest2 = function(y) { this.value = y; } XTest2.prototype = Test2.prototype; var x = new XTest2(3); alert(x.get()); XTest2.prototype.sub = function(x) { return this.value - x; } alert(x.sub(30)); var x = new Test2(3); alert(x.sub(30));
var add = new Function('a', 'b', 'return a + b;'); alert(add(5,6)); var mul = new Function('a,b', 'return a * b;'); alert(mul(5,6)); var div = Function('a', 'b', 'return a / b;'); alert(div(10,2));
var func = function(x) { if (x == 0) { return 1; } return x * arguments.callee.call(null, x - 1); } alert(func.apply(null, [5]));
RegExp
Test = function(x) { this.value = x; } XTest = function(x) { Test(x); } XTest.prototype = new Test(0); var x = new XTest(10); alert(x.value);
想定できる動作は、
Test = function(x) { this.value = x; alert('Test():' + this.value); } XTest = function(x) { for (var p in this) { alert(p + "=" + this[p]); } Test(x); for (var p in this) { alert(p + "=" + this[p]); } } XTest.prototype = new Test(0); var x = new XTest(10); alert(x.value); for (var p in x) { alert(p + '=' + x[p]); }
実際に動かすと、thisが同一と仮定すると
Test = function(x) { this.value = x; } var test = new Test(10); XTest = function(x) { Test(x); } XTest.prototype = test; var xtest = new XTest(11); var xtest2 = new XTest(12); alert(test.value); alert(xtest.value); alert(xtest2.value); test.value = 38; alert(test.value); alert(xtest.value); alert(xtest2.value); xtest.value = 40; alert(test.value); alert(xtest.value); alert(xtest2.value);
む、コンストラクタのスコープで代入しないとプロパティが作られないということのようだ(というか実行コンテキストのthisが別のものになる)。(ECMAScriptのnew expressionの仕様(11.2.2)ではこの部分の詳細な動作は規定されていないように見えるけど、違うところを読んでいるかも——追記:規定されるもなにも定義した通りに動作しているだけ)
結論:オブジェクトによって異なるプロパティ値が必要な場合、コンストラクタから呼び出したコンストラクタ内で定義したプロパティはコンストラクタ内で上書きしなければならない。もしプロパティの初期化処理を共通化したいなら、こうすりゃいいかな。
function setValue(o, v) { o.value = v; } Test = function(x) { setValue(this, x); } XTest = function(x) { setValue(this, x); } XTest.prototype = new Test(0); var x = new XTest(10); alert(x.value);
別の言い方をすると、クラス変数に相当するものは、prototypeとして利用するオブジェクトのプロパティを利用すれば良い。と書いたけどそれだけでは間違い。自分をthisとして代入するとその時点で新たなプロパティが作られるので、書き換え可能なクラス変数とはならない(読み込み専用となる)。あくまでもprototypeののプロパティを利用する。
function ctr_in_ctr5() { Test = function(x) { this.classvar = x; } XTest = function() { ; } XTest.prototype = new Test(30); XTest.prototype.cvarset = function(x) { XTest.prototype.classvar = x; } XTest.prototype.cvarget = function() { return XTest.prototype.classvar; } var x = new XTest(); alert(x.cvarget()); var y = new XTest(); alert(y.cvarget()); x.cvarset(31); alert(x.cvarget()); alert(y.cvarget()); }
ジェズイットを見習え |
> 3. その中でTest()を呼ぶ(thisは、1で作ったオブジェクト)<br>この3が間違ってます。<br>XTest(10)でも、new XTest(10)でも、ブラウザで実行してるなら、window.value = 10になります。<br>ECMAScript的にも、この挙動であってます。<br><br>Test = function(x) { this.value = x; }<br>XTest = function(x) { Test.apply(this,arguments); }<br>x = new XTest(10)<br><br>これだとx.value = 10になります。
ああ、なるほど。ありがとうございます。<br>TextもXTestもグローバルオブジェクトの中で定義されているから、明示的なnewの直後の呼び出しのXTestについてはthisは新しく作られたオブジェクトだけど、Test自体にはthisは与えてないということですね。