var Foo = (function () {
var cls = function () {
this.prototype = {
sayhi: function () {
alert('hi');
}
};
};
cls.staticMethod = function () {};
return cls;
})();
var f = new Foo();
Why can't i access my sayhi method? Doesn't this refer to the cls variable?
You are attempting to set the prototype property on every instance of cls. What you actually want to do is set the prototype property of cls itself:
var Foo = (function () {
var cls = function () {}; // Constructor function
cls.prototype = { // Prototype of constructor is inherited by instances
sayhi: function () {
alert('hi');
}
};
return cls;
})();
Related
So i have this code:
function Class1() {
this.i = 1;
var that=this;
function nn() {
return 21;
}
this.aa = function() {
nn();
};
this.bb = function() {
this.aa();
};
this.cc = function() {
this.bb();
};
}
var o = new Class1();
var b=o.cc();
alert(b); //undefined
But when the alert is fired, I get an undefined error and not 21, Does the private method can not use a return? Thanks!
When using the function() {} syntax to define a function, you always explicitly need to return the value, i.e. not only from nn, but from all intermediate functions as well.
function Class1() {
this.i = 1;
var that = this;
function nn() {
return 21;
}
this.aa = function() {
return nn();
}
this.bb = function() {
return this.aa();
}
this.cc = function() {
return this.bb();
}
}
var o = new Class1();
var b = o.cc();
alert(b); // "21"
Apart from the answer above, the 'this' context seems weird in your functions. Maybe you are better of with arrow functions if you dont want to bind the this context to each function. I also think that it is better to actually separate private and public functions when using a 'class' like this.
function Class1() {
var _nn = function () {
return 21;
}
var _aa = function () {
return _nn();
}
var _bb = function () {
return _aa();
}
var cc = function () {
return _bb();
};
return {
cc
};
}
var o = new Class1();
var a = o.cc();
console.log(a);
Much easier to understand that it is only cc that is a public function.
So with arrow function it would instead look like this, and you can use the Class1 this context inside of your private functions without doing
var that = this; or using bind.
function Class1() {
this.privateThing = 'private';
var _nn = () => { return this.privateThing; };
var _aa = () => { return _nn(); };
var _bb = () => { return _aa(); };
var cc = () => { return _bb(); };
return {
cc
};
}
I'm trying to create a function constructor:
var obj = function() {
this.num = 2;
this.func = function() {
// need to access the **instance** num variable here
};
};
var instance = new obj();
I need to access the instance properties from a propery (which is the function func) of the object. But it doesn't work, since this is always the current function..
Store this in a variable which func can access:
var obj = function() {
var _this = this;
_this.num = 2;
_this.func = function() {
console.log(_this.num);
};
};
Please, use well-known approach, store this into separate field:
var obj = function() {
self = this;
self.num = 2;
self.func = function() {
alert(self.num);
// need to access the **instance** num variable here
};
};
var instance = new obj();
This is the pattern I use for the problem:
var obj = function(){
var self = this;
this.num = 2;
this.func = function() {
console.info(self.num);
};
};
var instance = new obj();
The variable self now can be accessed in all function of obj and is always the obj itself.
This is the same then:
var obj = function(){
var self = this;
self.num = 2;
self.func = function() {
console.info(self.num);
};
};
var instance = new obj();
You can do it using the Custom Constructor Functions, used to create a custom constructor and it's accessed without any problem, try it:
var Obj = function () {
this.num = 2;
this.func = function () {
alert("I have " + this.num);
return "I have " + this.num;
};
};
var instance= new Obj();
instance.func();//will return and show I have 2
This doesn't work because f.bar.bar() in undefined.
var myFunction = function(foo){
this.foo = foo;
this.bar = {
bar: function(){
return this.foo;
}
}
}
var f = new myFunction('foo');
alert(f.bar.bar());
You can always declare a variable in the parent scope:
var myFunction = function(foo){
var func = this;
this.foo = foo;
this.bar = {
bar: function(){
return func.foo;
}
}
}
var f = new myFunction('foo');
alert(f.bar.bar());
I write a extend method to achieve inheritance in javascript:
function Class() {}
Class.prototype.create = function () {
var instance = new this();
instance.init();
return instance;
}
// extend method
Class.extend = Class.prototype.extend = function (props) {
var SubClass = function () {};
SubClass.prototype = Object.create(this.prototype);
for (var name in props) {
SubClass.prototype[name] = props[name];
}
SubClass.prototype.constructor = SubClass;
if (this.prototype.init) {
SubClass.prototype.callSuper = this.prototype.init;
}
SubClass.extend = SubClass.prototype.extend;
SubClass.create = SubClass.prototype.create;
return SubClass;
}
// level 1 inheritance
var Human = Class.extend({
init: function () {
}
});
// level 2 inheritance
var Man = Human.extend({
init: function () {
this.callSuper();
}
})
// level 3 inheritance
var American = Man.extend({
init: function () {
this.callSuper();
}
})
// initilization
American.create();
Then the develop tool report Maximum call stack size exceeded
I think the callSuper method cause the problem, callSuper call init, and init call callSuper, both with the same context.
But I don't know how to fixed it!
Can anyone could help me? How to set the correct context?
You have a scope problem. Here is the solution:
function Class() {}
Class.prototype.create = function () {
var instance = new this();
instance.init();
return instance;
}
// extend method
Class.extend = Class.prototype.extend = function (props) {
var SubClass = function () {},
self = this;
SubClass.prototype = Object.create(this.prototype);
for (var name in props) {
SubClass.prototype[name] = props[name];
}
SubClass.prototype.constructor = SubClass;
if (this.prototype.init) {
SubClass.prototype.callSuper = function() {
self.prototype.init();
}
}
SubClass.extend = SubClass.prototype.extend;
SubClass.create = SubClass.prototype.create;
return SubClass;
}
// level 1 inheritance
var Human = Class.extend({
init: function () {
console.log("Human");
}
});
// level 2 inheritance
var Man = Human.extend({
init: function () {
console.log("Man");
this.callSuper();
}
})
// level 3 inheritance
var American = Man.extend({
init: function () {
console.log("American");
this.callSuper();
}
})
// initilization
American.create();
The key moment is to wrap init method in a closure:
SubClass.prototype.callSuper = function() {
self.prototype.init();
}
Here is a jsfiddle containing the solution http://jsfiddle.net/krasimir/vGHUg/6/
I am trying to get this function to get the correct scope for its "this" operator, but no luck. Inside the AssetName = function(options){ code block, I want the "this" to point to the class AssetName. What is it that I am missing? The scope of this right from the beginning is window.
Assetname: function(options){
var Base = WM.Utility.GenericFilter()
options = options;
if (typeof Object.create !== "function") {
// For older browsers that don't support object.create
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
var AssetName = {};
AssetName = function(options){
return function(){
var self = this;
debugger;
// Call the super constructor.
Base.call(this, options);
this.$mod.on('change', '#asset-name-quick-search', self,
this.search);
this.$mod.on('click', '.close', self, this.remove);
this.initTypeAhead();
this.$selectionList = this.$mod.find("#asset-name-selection-list");
this.assetListItems = [];
return this;
}(options, AssetName);
}
// The AssetName class extends the base GenericFilter class.
AssetName.prototype = Object.create(Base.prototype);
AssetName.prototype.initTypeAhead = function(){
var options = {};
options.source = _.pluck(this.collection, 'asset_name');
options.items = 8;
this.$mod.find('#asset-name-quick-search').typeahead(options);
};
AssetName(options);
return AssetName;
},
AssetName = function(options){
return function(){
var self = this;
debugger;
// Call the super constructor.
Base.call(this, options);
this.$mod.on('change', '#asset-name-quick-search', self, this.search);
this.$mod.on('click', '.close', self, this.remove);
this.initTypeAhead();
this.$selectionList = this.$mod.find("#asset-name-selection-list");
this.assetListItems = [];
return this;
}(options, AssetName);
}
change to
AssetName = function(options){
var aa = function(){
var self = this;
debugger;
// Call the super constructor.
Base.call(this, options);
this.$mod.on('change', '#asset-name-quick-search', self, this.search);
this.$mod.on('click', '.close', self, this.remove);
this.initTypeAhead();
this.$selectionList = this.$mod.find("#asset-name-selection-list");
this.assetListItems = [];
return this;
};
aa.call(AssetName,options);
}
In your code, the function aa is called as aa(options); so this is window.
[update]
I fix the bug with the following code:
AssetName = function (options) {
AssetName = function (options) {
var aa = function () {
alert(this);
return this;
};
aa.call(this, options);
}
AssetName.prototype.initTypeAhead = function () {
alert(1);
}
return new AssetName(options);;
};
var test = AssetName();
test.initTypeAhead();
But I suggest how about writing the code like bellow:
AssetName = function (options) {
AssetName = function (options) {
alert(this);
}
AssetName.prototype.initTypeAhead = function () {
alert(1);
}
return new AssetName();
};
var test = AssetName();
test.initTypeAhead();
You cam just move your var self = this out side of the anonymous returned function. Then you can use just use self.