i want to functionality something similar to get property of C# .net. for example
var method : function() {
return "something which always change";
},
var objectName = {
property : method()
};
so whenever i call objectName.property this should return the actual new values. not the value set at the time of declaration. is it possible.
In .net property hold the function address and that function get called each time. i want the functionality like that.
thanks,
Use Object.defineProperty to override the getter.
var counter = 0;
var method = function() {
return counter++;
};
function ObjectName() {}
Object.defineProperty(ObjectName.prototype, 'property', {
get: method
});
var objectName = new ObjectName();
console.log(objectName.property); // 0
console.log(objectName.property); // 1
JSBin Demo https://jsbin.com/racegeteni/edit?js,console
other way to write this in more like a .net c# style is
var o = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
console.log(o.a); // 7
console.log(o.b); // 8
o.c = 50;
console.log(o.a); // 25
For OOP reasons, you should treat an object as a Class in .Net.
For example:
var Superman = function () {
this.quality = 'charming';
this.height = "6'5\"";
this.fly = function() {
console.log('flying..');
}
this.save = function(name) {
console.log('Save ' + name);
}
return this;
};
var CK = Superman();
console.log(CK.quality);
CK.save('L. Lane');
Related
so I'm trying to write a simple game to work with objects and get used to manipulating and working with them. What I want to do is set base stats (user/programmer defined) and then use those base stats in a method to create a complex stat. sample code for what I'm trying to do:
var main = function() {
function Boss (name, lvl, str, dex, int) {
this.bName = name
this.level = lvl
this.strength = str
this.dexterity = dex
this.intelligence = int
this.pAttack = pAttack();
}
function pAttack() {
(2*this.level) + (2*this.strength);
}
var a1Boss = new Boss("test", 50, 500, 500, 500)
console.log(a1Boss.pAttack)
}
This returns undefined to the console, although everything else returns correctly. Should the pAttack function be set up as
var pAttack = function() {code}
Any help would be appreciated
If you want your method to be attached to the new object do this :
this.pAttack = pAttack;
// and the function should be initialized as a variable
var pAttack = function(){...};
If you want your method to be attached to the prototype :
Boss.prototype.pAttack = pAttack;
Lots of syntax errors.
function Boss (name, lvl, str, dex, int) {
this.bName = name;
this.level = lvl;
this.strength = str;
this.dexterity = dex;
this.intelligence = int;
this.pAttack = this.pAttack();
}
Boss.prototype = {
pAttack: function () {
return (2*this.level) + (2*this.strength);
},
pDefend: function () {
//Defend stuff
},
levelUp: function () {
this.level = this.level + 1;
}
};
var a1Boss = new Boss("test", 50, 500, 500, 500);
console.log(a1Boss.pAttack)
https://jsfiddle.net/sLhrek8h/1/
You've actually executed the method pAttack instead of assigning it. Since pAttack returns nothing, undefined is returned as an alternative.
So just don't execute it,
this.pAttack = pAttack;
or return something
function pAttack() {
return (2*this.level) + (2*this.strength);
}
Your function needs to return a value. I would create it as a method of the object, however, and call it as such:
var main = function() {
function Boss(name, lvl, str, dex, int) {
this.bName = name;
this.level = lvl;
this.strength = str;
this.dexterity = dex;
this.intelligence = int;
this.pAttack = function() {
return (2 * this.level) + (2 * this.strength);
}
}
var a1Boss = new Boss("test", 50, 500, 500, 500);
console.log(a1Boss.pAttack());
};
main(); // outputs '1100' to the console
Another solution that may help out depending on what you're doing in the long run is passing in arguments into your function, and returning that value.
function pAttack(level, strength) {
return (2*level) + (2*strength);
}
and calling it with
this.pAttack = pAttack(this.level, this.strength);
Currently pAttack is not invoked in the context of a Boss instance so this is not pointing at what you expect, you have 3 options
In all cases, don't forget to return from the pAttack function!
Option 1, Have instances inherit pAttack
After defining pAttack, add the following
Boss.prototype.pAttackFn = pAttack;
What does this do?
It makes all instances of Boss, i.e. Objects constructed by new Boss, inherit the function pAttack as the property pAttackFn so you can call it e.g.
this.pAttack = this.pAttackFn();
Option 2, Define the context of invocation using .call or .apply
this.pAttack = pAttack.call(this);
Option 3, Give pAttack parameters instead of relying on this
function pAttack(lvl, str) {
return (2 * lvl) + (2 * str);
}
Then
this.pAttack = pAttack(this.level, this.strength);
I want to bind the parameters of an Object to another Object, so they update whenever the other one updates aswell.
Object1 =
x: 1
Object2 =
x: Object1.x
y: 0
so that Object1.x = 2; updates Object2 aswell. (And the other way round)
How do I do that efficiently? I could use .watch and update the other one on each change, but I doubt that is a smart solution. Am I missing something?
Depending on the environment this has to run, a getter might be a suitable solution:
Object.defineProperty(Object2, 'x', {
get: function() {
return Object1.x;
},
enumerable: true
});
You might also want to define a setter to sync changes back.
You need to implement the observer/observable pattern.
I could use .watch and update the other one on each change, but I
doubt that is a smart solution
How you notify the other part if something changes? Why isn't a smart solution? It's just the solution!
Check this code listing I did to show you a possible implementation of objects capable of listening changes of other objects creating a base ObservableObject prototype (also available in JSFiddle!):
var ObservableObject = function () {
this._handlers = [];
this._disablePropertyChangeNotification = false;
};
ObservableObject.prototype = {
get disablePropertyChangeNotification() {
return this._disablePropertyChangeNotification;
},
set disablePropertyChangeNotification(value) {
this._disablePropertyChangeNotification = value;
},
listenPropertyChange: function (handler) {
this._handlers.push(handler);
},
notifyPropertyChange: function (propertyName) {
if (!this.disablePropertyChangeNotification) {
this._handlers.forEach(function (handler) {
handler(propertyName);
});
}
},
};
var A = function () {};
A.prototype = new ObservableObject();
Object.defineProperty(A.prototype, "name", {
get: function () {
return this._name;
},
set: function (value) {
this._name = value;
this.notifyPropertyChange("name");
}
});
var B = function () {};
B.prototype = new ObservableObject();
Object.defineProperty(B.prototype, "name", {
get: function () {
return this._name;
},
set: function (value) {
this._name = value;
this.notifyPropertyChange("name");
}
});
var someObjectA = new A();
var someObjectB = new B();
someObjectA.listenPropertyChange(function (propertyName) {
// This will prevent an infinite loop where
// property from A is set by B and viceversa
someObjectA.disablePropertyChangeNotification = true;
someObjectB[propertyName] = someObjectA[propertyName];
someObjectA.disablePropertyChangeNotification = false;
});
someObjectB.listenPropertyChange(function (propertyName) {
// This will prevent an infinite loop where
// property from A is set by B and viceversa
someObjectB.disablePropertyChangeNotification = true;
someObjectA[propertyName] = someObjectB[propertyName];
someObjectB.disablePropertyChangeNotification = false;
});
// We set name on A instance, and we print B instance name value
someObjectA.name = "hello world";
$(document.body).append("<p>someObjectB.name: " + someObjectB.name + "</p>");
// We set name on B instance, and we print A instance name value
someObjectB.name = "hello world changed";
$(document.body).append("<p>someObjectA.name: " + someObjectA.name + "</p>");
I have a Object based on some closure, and want to implement event scheme here:
var class1 = function(val1)
{
var val = val1;
//------ want to call a method of Object of class1--------
var self = this;
setTimeout(function()
{
self.onEvent();
}, 1000);
//----------------
return {
f1: function()
{
return val;
},
onEvent: function()
{
console.log('not implemented yet. Override');
}
};
};
var obj1 = class1(5);
console.log(obj1.f1()); //5
obj1.onEvent(); //not implemented yet. Override
obj1.onEvent = function()
{
console.log('event fired');
}
got error, and I know the reason, and I need a solution:
5
not implemented yet. Override
/....../app.js:9
self.onEvent();
^
TypeError: Object #<Object> has no method 'onEvent'
It is possible if this bind with addEventListener scheme like this:
(The idea based on
Implementing events in my own object
)
var class2 = function()
{
var _this = this;
_this.events = {};
var fireEvent = function(name, args)
{
if (!_this.events.hasOwnProperty(name)) return;
if (!args || !args.length) args = [];
var evs = _this.events[name];
var l = evs.length;
for (var i = 0; i < l; i++)
{
evs[i].apply(null, args);
}
};
setTimeout(function()
{
fireEvent('testEvent', ['hello'])
}, 1000);
return {
addEventListener: function(name, handler)
{
if (_this.events.hasOwnProperty(name))
_this.events[name].push(handler);
else
_this.events[name] = [handler];
}
};
};
var obj2 = class2();
obj2.addEventListener('testEvent',
function(data)
{
console.log('event fired: ' + data);
});
event fired: hello
However, I prefer not to use addEventListener but .onEvent() scheme.
Is it possible? Perhaps it is possible using call/apply.
Thanks for your advice.
In your first block of code, you are returning an object, which is different from this or self.
You don't necessarily have to return this in your constructors but you should assign your functions on the returned object. If you create a variable for the object you want to return, you can use it in your setTimeout callback like so:
var class1 = function(val1)
{
var val = val1;
var obj = {
f1: function()
{
return val;
},
onEvent: function()
{
console.log('not implemented yet. Override');
}
};
setTimeout(function()
{
obj.onEvent();
}, 1000);
return obj;
};
For extra style points, you might want to capitalize the name of your constructors (and perhaps use new to instantiate them to make things clearer to your readers).
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
Javascript outer scope variable access
I have a javascript module that looks something like below. The main issue I'm having is how to access variables in the "this" scope from the private someOtherFunc. Is there a way to access this.myvar in the private someOtherFunc
var mymodule = (function(){
return {
MyObj : function() {
this.myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
//this doesn't seem to work
this.myvar = 456;
};
}
}
}
The idea is that I want to be able to do something like
new mymodule.MyObj().publicfunc, but make the someOtherFunc private
Forget my previous answer. You can do this just by adding a private version of this.
var mymodule = (function() {
return {
MyObj : function() {
this.myvar = 123;
var that = this;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
that.myvar = 456;
};
return this;
}
};
});
Bear in mind that, with your code, every time you call MyObj you get a new object.
So this would do what you want:
>var o = new mymodule().MyObj()
>o.myvar
123
>o.publicfunc()
>o.myvar
456
but not this
>var m = new mymodule()
>m.MyObj().myvar
123
>m.MyObj().publicfunc()
>m.MyObj().myvar
123
If that's not what you want, consider doing something like this
var mymodule = (function() {
var myObj = null;
this.MyObj = function() {
if(myObj != null)
return myObj;
myObj = {};
myObj.myvar = 123;
myObj.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function() {
myObj.myvar = 456;
};
return myObj;
};
});
Declare myvar using the var keyword, making it private, then access it without the this.:
function MyObj(){
var myvar = 123;
this.publicfunc = function() {
someOtherFunc();
};
var someOtherFunc = function(){
alert(myvar);
};
}
var o = new MyObj();
o.publicfunc();
If you need public access to myvar then create a public getter/setter.
jsFiddle Demo
I think what you're looking for is a way to encapsulate myvar for changes. When some of the other answers run, myvar usually will stay as 123 because the initially returned object from mymodule holds on to that initial value.
Return a function that gets the value of myvar even after it's been modified, and I think that helps your problem.
Here's the code that works for me:
var mymodule = (function(){
var myvar = 123,
publicfunc = function() { myvar = 456 },
getMyVar = function() { return myvar; };
return {
someOtherFunc : publicfunc,
myPublicVar : getMyVar
};
}());
mymodule.someOtherFunc();
alert(mymodule.myPublicVar()); //gives you 456
JSFiddle here.
I hope this helps.
Why not build it a little more deliberately?
// this one returns an object used like:
// myModule.myInt; /* 456 */
// myModule.myFunc(); /* 124 */
var myModule = (function () {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) { return num + 1; },
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
}());
I went through the trouble of explicitly naming the returned, public object, but it's now very clear what is and isn't public, and yet, each one of those things will have access to the variable versions of one another, with the one exception being that if you change myModule.myInt or publicData, they will no longer be equal.
To demonstrate what I mean in the comments below, creating multiple instances with their own private data/methods, I just add in one more layer of function-scope:
var myModule = (function () {
var static_int = 789,
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
You now use it like:
var newModule = myModule(/* instance parameters */);
newModule.myFunc();
...or
var num = myModule(/* instance parameters */).myFunc();
If you wanted to save memory, you could have static helper functions inside of the static-layer:
var myModule = (function () {
var static_int = 789,
static_addOne = function (num) { return num + 1; },
static_divideBy = function (dividend, divisor) { return dividend/divisor; },
makeInstance = function (/* any constructor values */) {
var secretData = 123,
publicData = 456,
publicFunc = function () { return privateFunc(secretData); },
privateFunc = function (num) {
console.log(static_int);
return num + 1;
},
public_interface = {
myInt : publicData,
myFunc : publicFunc
};
return public_interface;
};
return makeInstance;
}());
And now you have "private" functions which are only written one time (ie: you save memory), but any instance can use those functions.
Here's the catch:
Because of how scope and closure work, the static functions have NO access to values inside of the instance (functions inside have access to the static functions, not the other way around).
So, any static helper functions MUST have the values passed to them as arguments, and if you're modifying a number or a string, you MUST return the value out of that function.
// inside of a private method, in any instance
var privateString = "Bob",
privateFunc = function () {
var string = static_helper(privateString);
privateString = string;
//...
};
You don't return anything from MyObj.
return this;
should fix it.
Use the bind method:
var someOtherFunc = function() {
this.myvar = 456;
}.bind(this);
This is what I'm doing right now.
var foo = function() {
var x = someComplicatedComputationThatMayTakeMoreTime();
this.foo = function() { return x; };
return x;
}
It works but only if foo is called as a function like so
foo();
But what if I want to call it as a normal variable with a value? I could modify the code to be
var foo = function() {
var x = someComplicatedComputationThatMayTakeMoreTime();
this.foo = x;
return x;
}
That would allow me to only call it once as a function and after that as a regular variable. But it's still not what I want. Plus it gets complicated if it accidentally gets called as a function again, returning an error.
Is this even possible in JavaScript?
BTW, this is for a Chrome/Firefox extension, so IE compatibility does not matter.
Ended up using toString because getters don't allow me to redefine the whole attribute, a function must be associated with it. And toString has cleaner syntax.
How about using toString?
var foo = function() {
function someComplicatedComputationThatMayTakeMoreTime() {
//your calculations
}
return {
toString: function() {
return someComplicatedComputationThatMayTakeMoreTime();
}
}
}
More about Object-to-Primitive Conversions in JavaScript
EDIT based on comment. Use a singleton (I think it's called):
myObject.prop = (function(){
function someComplicatedComputationThatMayTakeMoreTime() {
//your calculations
}
return {
toString: function() {
return someComplicatedComputationThatMayTakeMoreTime();
}
}
})()
If only Internet Explorer didn't exist, you could use getters and setters as described by John Resig in this blog article:
John Resig: JavaScript Getters and Setters
... They allow you to bind special functions to an object that look like normal object properties, but actually execute hidden functions instead.
Using a function is your best option for now, however the new JavaScript standard (ECMAScript 5th Ed.) which is being implemented now by all major browser vendors, gives you a method to create accessor properties, where you can define a property with a get and set functions that will be internally called, without worrying to treat this properties as functions, e.g.:
var obj = {};
Object.defineProperty(obj, 'foo', {
get: function () { // getter logic
return 'foo!';
},
set: function (value) {
// setter logic
}
});
obj.foo; // "foo!", no function call
This new standard will take some time to be implemented for all browsers, (the IE9 preview version really disappointed me), and I wouldn't recommend you to use it for production, unless you have total control on the environment where your application will be used.
What I think you want is a lazily instantiated variable, which can be implemented like this.
var myProperty = null;
function getMyProperty() {
return (myProperty = myProperty || builder());
}
This is not practical on the web because IE does not support it, but you can look at
https://developer.mozilla.org/en/defineGetter for examples how to do this.
There are a couple ways to do it, here is one example:
var data = {};
data.__defineGetter__("prop",
(function () {
var value = null;
return function () {
if (null == value) {
value = getYourValueHere();
}
return value;
};
})());
and now you can use it like:
var a = data.prop;
var b = data.prop;
I would recommend a variation on ChaosPandion's answer, but with a closure.
var myProperty = (function () {
var innerProperty = null;
return function() {
return (innerProperty = innerProperty || someComplicatedComputationThatMayTakeMoreTime());
};
})();
and then use myProperty() every time you need to access the variable.
You could define a JavaScript getter. From the Apple JavaScript Coding Guidelines:
myObject.__defineGetter__( "myGetter", function() { return this.myVariable; } );
var someVariable = myObject.myGetter;
See John Resig's post, JavaScript Getters and Setters, and the Defining Getters and Setters page at the Mozilla Developer Centre for more information.
I would use explicit lazy evaluation. Here's my implementation of it based on Scheme's take:
var delay, lazy, force, promise, promiseForced, promiseRunning;
(function () {
var getValue = function () {
return this.value;
};
var RUNNING = {};
var DelayThunk = function (nullaryFunc) {
this.value = nullaryFunc;
};
DelayThunk.prototype.toString = function () {
return "[object Promise]";
};
DelayThunk.prototype.force = function () {
if (promiseRunning (this)) {
throw new Error ("Circular forcing of a promise.");
}
var nullaryFunc = this.value;
this.value = RUNNING;
this.value = nullaryFunc ();
this.force = getValue;
return this.value;
};
var LazyThunk = function (nullaryFunc) {
DelayThunk.call (this, nullaryFunc);
};
LazyThunk.prototype = new DelayThunk (null);
LazyThunk.prototype.constructor = LazyThunk;
LazyThunk.prototype.force = function () {
var result = DelayThunk.prototype.force.call (this);
while (result instanceof LazyThunk) {
result = DelayThunk.prototype.force.call (result);
}
return force (result);
};
delay = function (nullaryFunc) {
return new DelayThunk (nullaryFunc);
};
lazy = function (nullaryFunc) {
return new LazyThunk (nullaryFunc);
};
force = function (expr) {
if (promise (expr)) {
return expr.force ();
}
return expr;
};
promise = function (expr) {
return expr instanceof DelayThunk;
};
promiseForced = function (expr) {
return expr.force === getValue || !promise (expr);
};
promiseRunning = function (expr) {
return expr.value === RUNNING || !promise (expr);
};
}) ();
Example Syntax:
var x = lazy (function () { return expression; });
var y = force (x);
var z = delay (function () { return expression; });
var w = force (z);
Note values are stored once evaluated, so repeated forcing will not do extra computations.
Example usage:
function makeThunk (x, y, z) {
return lazy (function () {
// lots of work done here
});
}
var thunk = makeThunk (arg1, arg2, arg3);
if (condition) {
output (force (thunk));
output (force (thunk)); // no extra work done; no extra side effects either
}
You can use the javascript Proxy class for creating such functionality.
var object = {};
var handler = {
resolvers: {},
get ( target, property, proxy ) {
if ( ! target.hasOwnProperty( property ) && this.resolvers.hasOwnProperty( property ) ) {
// execute the getter for the property;
target[ property ] = this.resolvers[ property ]();
}
return target[ property ];
},
set ( target, property, value, receiver ) {
// if the value is function set as a resolver
if ( typeof value === 'function' ) {
this.resolvers[property] = value;
// otherwise set value to target
} else {
target.property = value;
}
},
has ( target, property, receiver ) {
//true when proxy handler has either a resolver or target has a value;
return this.resolvers.hasOwnProperty( property ) || target.hasOwnProperty( property );
}
};
var lazyObject = new Proxy( object, handler );
Now you can use it like this:
'exampleField' in lazyObject; //returns false
lazyObject.exampleField = function(){ return 'my value' }; // add a resolver function
'exampleField' in lazyObject; //returns true
lazyObject.exampleField; //executes your resolver function and returns 'my value'
This example is to demonstrate the working. You can change after your needs.
Here is a fiddle with a demonstration