最初の質問
昨日、ECMAScript 5 Object.create() について読みました。そして、プロトタイプとそのコンストラクターを設定する代わりに、このメソッドを使用してコード内にプロトタイプ チェーンの構築を開始したかったのです。書き込み可能で構成可能なものなどを直接設定できるのが気に入っています。
こんな感じでやってみた
function printobject(msg, obj) {
if (msg) {
document.write("<b>" + msg + "</b><br>");
document.write("<hr><br>");
}
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
if (obj[prop].toString() !== "[object Object]") {
document.write(prop + " : " + obj[prop] + "<br>");
}
else {
document.write("<b>" + prop + " : " + obj[prop] + "</b><br>");
printobject("", obj[prop]);
}
}
}
if (msg) {
document.write("<br><hr><br>");
}
};
var base = {
extend: function () { //extend this Object
var args = Array.prototype.slice.call(arguments);
printobject("Arguments to Extend", args)
var that = Object.create(this, (args ? args.shift() : {}));
var arg = args.shift() || {};
printobject("Copy Properties to New Object", arg);
for (var prop in arg) {
that[prop] = arg[prop];
}
// Object.freeze(that);
return that;
},
create: function () { //Creates new instances of the Object
var that = Object.create(this, {
extend: {
value: null,
writable: false,
configurable: false
}, //sets extend and create to null so you cant create a new instance when used create ( use extend instead);
create: {
value: null,
writable: false,
configurable: false
}
});
that.init.apply(that, arguments); //call init function for the new created object;
return that;
},
init: function () {
printobject("No Initfunction supplied for New Object", this);
} // Empty init function for fallback
}
var Human = base.extend({
name: {
value: "test"
}
}, {
init: function (name) {
alert(name + " has been created");
this.name = name;
},
walk: function () {
alert(this.name + " walks");
}
});
var Human1 = Human.create("test2");
//alert("Human1 - Name:" + Human1.name);
Human1.walk();
Human.walk = function () {
alert("Walk has been overwritten")
}; //Object freezed
Human1.walk();
Human1.create = function () {
alert("Overwrite create");
}; //Doesnt exist in created Object
Human1.create(); ?
- で指定されたメソッド
Human
は、RAM に 1 回しか存在しませんか? そしてHuman1.walk()
それを指す? - これは、このようにする正しいアプローチなのだろうか?私はJavaScriptに比較的慣れていません。
これはjsfiddleのコードです。
答え
まず第一に、物事をより明確にすることがたくさんあります=)しかし、1:私がこのようにすると、インスタンスはコンストラクターのプロトタイプから継承します(?)
Nothing = {};
function base() {
this.inherit = function(constructor) {
alert("inherit");
var obj = constructor;
obj.constructor = constructor;
obj.prototype = this;
return obj ;
}
;}
base.prototype = Nothing;
base.constructor = base;
var Top = new base();
var Human = Top.inherit(function(name) {
this.name = name;
});
var Paul = new Human("Paul");
alert(Paul.name);
alert(Paul instanceof Human); //true `
2: したがって、 instanceof 演算子はこの Code で壊れません (関数に対してのみ機能することは私には明らかです)
しかし、このように書いても、Paul は依然として Top のプロトタイプから inherit() メソッドを継承しており、それを上書きする必要があります。
そして、Objkect.defineproperty (?) を使用しない限り、wrtable のようなプロパティ記述子を設定できません。
Object.create() を使用して Objects から継承することと、プロトタイプとコンストラクターを設定することの主な利点は何ですか? =)
3: ああ thx、はい、それは基本オブジェクトの拡張ではありません =) 提案のための thx =)
すべての努力のためのThx =)
答え
わかりましたので、私がそうするとき
なし = {}
base.prototype = なし;
これは Object.prototype までプロトタイプチェーンを上ることを妨げませんか? そうでない場合、これを行う方法はありますか? =) ( Object.create(null); ) はこれを行いますか?
そして、私は設定しなければならないと思った
base.prototype.constructor = ベース;
そうでなければ、のプロトタイプコンストラクター
var Top = new base();
プロトタイプが Nothing に設定されている場合、Nothings になるか、プロトタイプ チェーンのどこかからコンストラクターを基本継承しません ->
baseof のトップ インスタンス // false
アップデート
私は今、このような方法でそれをやった:
var base = {
// a tiny little selfmade prototypical inheritance system
// you are free to add function arguments for extending the created objects
// neither instanceof nor .constructor is featured, because "classes" are no functions
create: function(extension,desc) {
// instances inherit from the proto objects
var newInst = Object.create(this.proto, desc);
if(this.proto.childExtendable) //if Subclass allows its Children to be Extendible, do so
newInst.extend(extension);
if(newInst.init||this.proto.init) //4
newInst.init()
return newInst
},
inherit: function(props) {
// the "class" inherits static methods from the class
var sub = Object.create(this);
// and the proto objects inherits from the parent proto
sub.proto = Object.create(this.proto);
props.protect = this.protect;
if(props.childExtendable)
props.extend = this.extend;
this.extend.call(sub.proto, props);
return sub;
},
extend: function (props) {
for (var prop in props) {
var propmatch = prop.match(/(.*?)__(.{1,5}?)__(.*)/)||["",prop,"",""];
this[propmatch[1]+propmatch[3]] = props[prop];
if(propmatch[2])
this.protect(propmatch[1]+propmatch[3],propmatch[2]);
}
},
protect: function(prop,flags) { //with each call it toggles the given flags, so you can protect funcitons given to the inherit function ;; //This should be available to all childs, but adding it to the base.proto, it changes Object.prototyppe ( therefore not a good idea)
var d = Object.getOwnPropertyDescriptor(this, prop);
if (flags.match(/w/)){
Ti.API.info("Setting writable for propertie " + prop + " in Object " + this + " to " + !d.writable);
Object.defineProperty(this, prop, {writable:!d.writable});};
if (flags.match(/c/)){
Ti.API.info("Setting configurable for propertie " + prop + "in Object " + this);
Object.defineProperty(this, prop, {configurable:!d.configurable});};
if (flags.match(/e/)){
Ti.API.info("Setting enumerable for propertie " + prop + "in Object " + this);
Object.defineProperty(this, prop, {configurable:!d.enumerable});};
if (flags.match(/a/)){
Ti.API.info("Setting enumerable for propertie " + prop + "in Object " + this);
Object.preventExtensions(this);};
},
init: function() {},
proto: Object.prototype // or null, if you want
};
var Human = base.inherit({ //will be put in Human.proto
childExtendable:true,
init:function() {alert("Humans Init for all Instances")},
say:function() { alert("Hi, I'm "+this.name); }
});
Human.proto.name = "default"; // You could use an argument to the inherit function
// I just want to make clear what happens
Ti.API.info(Object.getPrototypeOf(Function) + "a");
var paul = Human.create({ //extends this object
name: "Paul",
test: function() {alert("test")},
init__wce__: function() {alert("Pauls Own Init")},
say__w__ : function() { alert("Hi, I'm" + this.name + "s Own Function")}
});
paul.name = "Paul"; // and again, the create function might do it for you
paul.say = function() {alert("Pauls say is overwritten")} // define init without __wce__ and it will be overwritten
paul.say(); // -> "Hi, I'm Paul"
誰かが気にかけている場合でも
、jsfiddle はこれを実行しません。Titanium は、おそらくいくつかの厳密なモード (??) を期待どおりに実行します。