MyGlobalObject;
function TheFunctionICanUseRightAwaySingleForAllInstansesAndWithoutInstanse() {
function() {
alert('NO CONSTRUCTOR WAS CALLED');
}
};
长命名函数必须可以从MyGlobalObject
调用,而后者必须在加载脚本后始终作为全局(到window
)变量使用。它应该支持符合最新标准的可扩展性。
我正处于如何为应用程序构建JS库的架构困境(几乎100%JS)。
我们需要一个对象,即window.MyObject
(就像一个模块,比如jQuery),所以
可以使用
创建VAR1
var MyGlobalObjConstructor = function(){
this.GlobalFunctionInObject = function(){
alert('called with MyGlobalObj.GlobalFunctionInObject()');
}
};
window.MyGlobalObj = new MyGlobalObjConstructor();
MyGlobalObj
是否可扩展?我可以创建子对象,它将继承MyGlobalObj
的当前状态(扩展函数/属性MyGlobalObj.NewFunc
,例如)?使用原型(VAR3)之间的主要区别是什么?
By GlobaldFunction
我指的是所有初始化/实例化(可能是实例化的)实例的单个实例。
或者
VAR2
var MyGlobalObj = {
GlobalFunctionInObject: function...
GlobalFunctionInObject2: function...
};
MyGlobalObj.GlobalFunctionInObject();
// here I lose all hierarchy elements, no prototype,
// can I use GlobalFunctionInObject2 in GlobalFunctionInObject?
或者
VAR3
var MyGlobalConstuctor = function(){} // already 'well-formed' object
MyGlobalConstuctor.prototype.GlobalFunctionInObject = function...
};
var MyGlobalObj = new MyGlobalConstuctor();
// so I'm sceptical to NEW, because I have ALREADY wrote my functions
// which I expect to be in memory, single instance of each of them,
// so creating MyObject2,3,4 with NEW MyGC() makes no sense to me.
// DO I REALLY HAVE TO USE "MyGlobalConstuctor.prototype." FOR EACH FUNCTION?!!!!
将MyGlobalObj
定义为函数和作为对象(func或VAR2的结果)有什么区别?
OR VAR4?
我在Chrome Debugger中看到了原型和__proto__
特殊字段。我读过那没关系,但为什么他们没有保存在一个原型中?
那么,实施window.MyObject
的正确/最佳方式是什么,所以可以MyObject.MyFunction();
变体1 2和3有什么不同(赞成/反对)?
答案 0 :(得分:30)
function SomeType() {
var priv = "I'm private";
this.publ = "I'm public";
this.action = function() {
return priv + this.publ;
};
}
var obj = new SomeType();
使用此方法,每次调用new SomeType()
时都会创建一个新对象,创建所有方法并将所有此方法添加到新对象中。每次创建对象时。
obj instanceof SomeType
将返回true private
,而非protected
,子类型无法访问function SubType() {
SomeType.call(this);
this.newMethod = function() {
// can't access priv
return this.publ;
};
}
var child = new SubType();
child instanceof SomeType
将返回false,没有其他方法可以知道child是否具有SomeType方法,而不是逐个查看它们。
var obj = {
publ: "I'm public",
_convention: "I'm public too, but please don't touch me!",
someMethod: function() {
return this.publ + this._convention;
}
};
在这种情况下,您正在创建单个对象。如果您只需要这种类型的一个实例,那么它可能是最佳解决方案。
您可以继承对象进行原型设计。
var child = Object.create(obj);
child.otherMethod = function() {
return this._convention + this.publ;
};
如果您使用的是旧浏览器,则需要保证Object.create
作品:
if (!Object.create) {
Object.create = function(obj) {
function tmp() { }
tmp.prototype = obj;
return new tmp;
};
}
要知道某个对象是否是另一个对象的原型,您可以使用
obj.isPrototypeOf(child); // true
更新:这是模式ES6类是的糖语法。如果您使用的是ES6课程,那么您可以了解这种模式。
class SomeType {
constructor() {
// REALLY important to declare every non-function property here
this.publ = "I'm public";
this._convention = "I'm public too, but please don't touch me!";
}
someMethod() {
return this.publ + this._convention;
}
}
class SubType extends SomeType {
constructor() {
super(/* parent constructor parameters here */);
this.otherValue = 'Hi';
}
otherMethod() {
return this._convention + this.publ + this.otherValue;
}
}
function SomeType() {
// REALLY important to declare every non-function property here
this.publ = "I'm public";
this._convention = "I'm public too, but please don't touch me!";
}
SomeType.prototype.someMethod = function() {
return this.publ + this._convention;
};
var obj = new SomeType();
如果你没有继承并且记得重新分配构造函数属性,你可以重新分配原型而不是添加每个方法:
SomeType.prototype = {
constructor: SomeType,
someMethod = function() {
return this.publ + this._convention;
}
};
如果页面中有下划线或jquery,则使用_.extend或$ .extend
_.extend(SomeType.prototype, {
someMethod = function() {
return this.publ + this._convention;
}
};
引擎盖下的new
关键字只是这样做:
function doNew(Constructor) {
var instance = Object.create(Constructor.prototype);
instance.constructor();
return instance;
}
var obj = doNew(SomeType);
你所拥有的是一种功能,而不是没有方法;它只有prototype
属性和函数列表,new
运算符意味着创建新对象并使用此函数的原型({{1} })和Object.create
属性作为初始化程序。
constructor
你可能认为它看起来像一套超级变种2 ......而且你是对的。它类似于变体2,但具有初始化函数(构造函数);
function SubType() {
// Step 1, exactly as Variation 1
// This inherits the non-function properties
SomeType.call(this);
this.otherValue = 'Hi';
}
// Step 2, this inherits the methods
SubType.prototype = Object.create(SomeType.prototype);
SubType.prototype.otherMethod = function() {
return this._convention + this.publ + this.otherValue;
};
var child = new SubType();
和child instanceof SubType
将同时返回child instanceof SomeType
好奇心:幕后true
运算符
instanceof
function isInstanceOf(obj, Type) {
return Type.prototype.isPrototypeOf(obj);
}
当你在幕后做__proto__
Object.create(obj)
function fakeCreate(obj) {
var child = {};
child.__proto__ = obj;
return child;
}
var child = fakeCreate(obj);
属性直接修改对象的隐藏__proto__
属性。由于这会破坏JavaScript行为,因此它不是标准的。标准方式是首选([Prototype]
)。
Object.create
键可以改变对象的原型__proto__
哦,是的,函数是对象所以他们有方法,我会提到三个:.call(),.apply()和.bind()
在函数上使用.call()时,可以在函数内部传递一个额外的参数 context ,var child = { __proto__: obj };
obj.isPrototypeOf(child); // true
的值,例如:
this
因此,当我们执行var obj = {
test: function(arg1, arg2) {
console.log(this);
console.log(arg1);
console.log(arg2);
}
};
// These two ways to invoke the function are equivalent
obj.test('hi', 'lol');
// If we call fn('hi', 'lol') it will receive "window" as "this" so we have to use call.
var fn = obj.test;
fn.call(obj, 'hi', 'lol');
时,我们将对象SomeType.call(this)
传递给函数this
,因为您记得此函数会向对象SomeCall
添加方法。
我的意思是你的对象所拥有的任何属性都不是函数必须在构造函数上定义,而不是在原型上定义,否则你将面临一个更令人困惑的JS问题。你可以see it here,但它不在这个问题的焦点之内。
实际上你可能没有看到差异,这就是它成为一个危险的错误。每个函数的原型对象都有一个this
属性,因此您可以从实例访问构造函数。
constructor
这不是最佳做法,因为不是每个人都知道它,但有时它会有所帮助。但如果你重新分配原型......
function A() { }
// When you create a function automatically, JS does this:
// A.prototype = { constructor: A };
A.prototype.someMethod = function() {
console.log(this.constructor === A); // true
this.constructor.staticMethod();
return new this.constructor();
};
A.staticMethod = function() { };
A.prototype = {
someMethod = function() {
console.log(this.constructor === A); // false
console.log(this.constructor === Object); // true
this.constructor.staticMethod();
return new this.constructor();
}
};
是一个新对象,A.prototype
的实例比原型Object
和Object.prototype
为Object.prototype.constructor
。令人困惑,对吧? :P
因此,如果您覆盖原型并且不重置"构造函数"如果您尝试使用"构造函数"访问某些静态方法的属性,你可能会发疯。
答案 1 :(得分:5)
我通常会回复一个具有属性的对象:
var newCat = function (name) {
return {name: name, purr: function () {alert(name + ' purrs')}};
};
var myCat = newCat('Felix');
myCat.name; // 'Felix'
myCat.purr(); // alert fires
您可以通过调用newCat函数并扩展您获得的对象来继承:
var newLion = function (name) {
var lion = newCat(name);
lion.roar = function () {
alert(name + ' roar loudly');
}
return lion;
}
如果你想要一个全局猫对象:
var cats = (function () {
var newCat = function (name) {
return {
name: name,
purr: function () {
alert(name + ' is purring')
}
};
};
return {
newCat: newCat
};
}());
现在你可以致电:
var mySecondCat = cats.newCat('Alice');