It is possible to create getters and setters in javascript as shown by
Object.defineProperty
__define***__
In all those instances, the name of the property is known.
Is it possible create a generic one.
By this I mean, I have a getter and or setter and it is called irrespective of the property name.
Is this possible?
If so, how?
regards.
Note:
I did find these after posting the question. Looks like it is currently not possible as the first answer stated.
Is it possible to implement dynamic getters/setters in JavaScript?
Monitor All JavaScript Object Properties (magic getters and setters)
To all time travelers like me:
It was not possible at the time the question was asked, but it is already possible in present versions of EcmaScript via so-called proxy objects. See more here:
Is it possible to implement dynamic getters/setters in JavaScript?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy
There is a non standard function __noSuchMethod__() which is executed when a non existing property is invoked as a function.
But I don't think there is exactly what you are looking for in JavaScript (yet).
Not possible in standard javascript at this point.
I suppose you are expected to handle this yourself:
if (!object.hasOwnProperty('foo')) {
// object has a foo property, its value might be undefined
} else if (typeof object.foo != 'undefined') {
// there is a foo property elsewhere on object's prototye chain with
// a value other than undefined
} else {
// the foo property might exist on the prototype chain with
// a value of undefined, or might not exist on the chain at all
}
I feel like you guys were looking for something like this
function getterSetter()
{
var valA;
this.set=function (propName,val)
{
if(typeof this[propName] =='function' )
{
return false;
}
this[propName]=val;
}
this.get=function (propName,val)
{
if(typeof this[propName] =='function' )
{
return false;
}
return this[propName];
}
}
Here the set and get methods are setter and getter. You can verify this with following code.
var testObj=new getterSetter();
testObj.set('valA',10);
alert(testObj.get('valA'));
Also, checking for the propName to set/get is not a function.
Related
This question already has answers here:
jquery: test whether input variable is dom element
(4 answers)
Closed 9 years ago.
I was wondering how can i pass two different type of value in a single function which accepts single parameter.
let a function is function a(b){return c;}
i'm trying to pass a string while calling the function a some places like a('a string value') then i'll do something with it. Now i need to pass a html element like a(jquery('#someDiv')) and then i'll some another stuff. I need to differentiate both in the function declaration.
Any idea from the experts?
Thanks in advance.
EDIT:
I was looking for a tip to check the data type i'm going to pass as the parameter of the function a. It can be a string or a number or an object or even a function. I don't want to use a fallback. I want to use the last else statement to through an error or exception.
The typeof operator can be used to test for strings.
if (typeof b == 'string') {
//handle string
}
The second part is a bit more tricky. typeof will return object for a jQuery object. I believe it is safe enough to check if the object's [[Prototype]] is the same as the jQuery constructor's prototype using Object.getPrototypeOf:
else if (Object.getPrototypeOf(b) === $.fn) {
//it is an object that inherits from the jQuery prototype
}
But that isn't supported in IE<9. If a fallback is necessary, instanceof will have a similar effect and can be used instead of Object.getPrototypeOf:
else if (b instanceof jQuery) {}
So a complete solution with old IE support:
if (typeof b == 'string') {
//handle string
} else if (b instanceof jQuery) {
//handle jQuery object
} else {
throw 'Invalid argument';
}
* Note that instanceof will return true even when a constructor "subclasses" jQuery (has a link in the prototype chain to jQuery), while Object.getPrototypeOf will only return true if the object's internal [[Prototype]] points to the same object as the jQuery constructor's prototype. It is rather rare when this will make a difference, but worth keeping in mind.
Nevertheless of these small quirks, this related question has instanceof as the accepted answer, as it is the most compatible solution.
And to explain a couple things, jQuery itself is not a constructor, but its prototype object is shared with jQuery.fn.init which is the actual constructor, and jQuery.fn is a shorthand for jQuery.prototype, so:
jQuery.fn.init.prototype === jQuery.prototype
jQuery.prototype === jQuery.fn
This is going a little off-topic already, so here's a more in-depth article for the interested readers: How jQuery instantiates objects as jQuery.fn.init, and what that means if you want to subclass jQuery
How do getter or setter works on object in javascript ?
i.e.
In python if I call a nonexistent method on an object I could intercept the call via getter and setter and in turn return from getter and setter.
How do I do similar functionality in JavaScript ?
https://github.com/Flotype/now/blob/master/lib/client/now.js implements this functionality somehow. I didn't understand the trick. can anyone explain ?
Creating the same functionality is virtually impossible in Javascript. My best guess would be something like this:
var getter = function (propName) {
if (propName in this) {
return this[propName];
} else {
return "no prop";
}
};
You can call this function on any object you like using this syntax:
a = { "test": "yes" };
b = {}
console.log(getter.call(a, "test"));
console.log(getter.call(b, "test"));
It's not the best solution but I don't think there's a better way.
1) You can use non-standart mozilla __noSuchMethod__ property.
2) EcmaScript 6 Harmony propose the Proxy object. See Simulating __noSuchMethod__
somebody know how to get typeof object under prototype property? i.e. I have the next code:
Object.prototype.someproperty = function(){
...do something...
console.log(typeof this);
..more...
}
in my code this results alway's "Function" because the constructor of objects is a function. when I call like this
Array.someproperty(); //In this i want get "array"
//or
String.someproperty(); //In this i want get "string"
I want get "Array" instead "function"... somebody know how?
The problem here is that this when called via Array and String is bound to the function and not an instance of the types. The only way I know of to determine which of these functions is being called is to do manual testing like the following
Object.prototype.someproperty = function() {
if (this === Array) {
return "array";
} else if (this === String) {
return "string";
}
...
}
In this case though you're not actually reporting the type of the object the prototype is being invoked from. The value "function" is quite accurate for that. This is more of a heuristic than a true type test
Finally along this time and with a lot of reading and learning, I have seen that it is very bad practice to extend the prototype objects. I thank you all for your support.
I want to add a method to every object.
When I just set Object.prototype.somefunction = ..., it will come up when somebody enumerates the object using the usual pattern:
for (i in o){
if (o.hasOwnProperty(i)){
// do something with object
}
}
I tried to set it higher up the prototype chain, but that is not possible (at least not possible in Chrome):
TypeError: Cannot set property 'blah' of undefined
Can I set some flag or something on the method so that it won't get enumerated, just like the native methods won't? (Or at least make hasOwnProperty() return false.)
Update: Sorry, I didn't look at it properly. I am using the ExtJS Framework and the object I was looking at had been processed by Ext.apply() which does the following:
for(var p in c){
o[p] = c[p];
}
That's where the "own property" flag gets lost.
So I guess I have no chance (in ECMAScript < 5) to inject a method into all objects that behaves like a native one?
I'm not sure I understand correctly. hasOwnProperty is needed exactly for this case, and enumerating an object via
for (i in o){
if (o.hasOwnProperty(i)){
// do something with object
}
}
should not include methods from Object.prototype. Can you please make a working example where you see this behaviour?
I also do not understand what you mean by
I tried to set it higher up the
prototype chain
as Object.prototype is the root of the chain, so you cannot get any higher.
In short, the solution is doing exactly what you claim you have done. If this does not work, probably you have made a mistake or found a bug.
I'm not sure what you mean. If a method/property is attached to the prototype, hasOwnProperty will return false. See this code:
function Con(){this.enumerableProp = true;};
Con.prototype.fun = function(){return 'that\'s funny'};
var fun = new Con;
alert(fun.hasOwnProperty('fun')); //=> false
alert(fun.hasOwnProperty('enumerableProp')); //=> true
So, what do you mean?
Make a base class and make all other classes extend it. Add the method to the base class.
ES5 has Object.getOwnPropertyNames() for this:
Object.prototype.lolwat = 42;
var obj = {
'foo': 1,
'bar': 2
};
Object.getOwnPropertyNames(obj); // ['bar', 'foo']
To see where it is supported: http://kangax.github.com/es5-compat-table/
However, for-in combined with a hasOwnProperty check should work too.
You get that error because there is nothing higher up the prototype chain.
Of note also is that adding to Object's prototype is not really recommended unless absolutely necessary for some reason
Edit: actually, my original answer was incorrect - as the others have pointed out, your object should not have that as own property if it's in Object's prototype.
In any case, if you want to create a prototype chain (or more importantly, avoid changing Object's prototype), you'll want to create your own class:
function MyBaseClass(){
}
MyBaseClass.prototype = new Object();
MyBaseClass.prototype.someMethod = function() { /* your method */ };
var o = new MyBaseClass();
o.hasOwnProperty('someMethod') //should be false
I'm working with XULRunner and came across the following pattern in a code sample:
var StrangeSample = {
backingStore : "",
get foo() { return this.backingStore + " "; },
set foo(val) { this.backingStore = val; },
func: function(someParam) { return this.foo + someParam; }
};
StrangeSample.foo = "rabbit";
alert(StrangeSample.func("bear"));
This results in "rabbit bear" being alerted.
I've never seen this get/set pattern used in Javascript before. It works, but I can't find any documentation/reference for it. Is this something peculiar to XUL, a recent language feature, or just something I missed? I'm puzzled because I was specifically looking for something like this a few months ago and couldn't find anything.
For reference, removing "get" or "set" results in a syntax error. Renaming them to anything else is a syntax error. They really do seem to be keywords.
Can anyone shed some light on this for me, or point me towards a reference?
As suggested by Martinho, here are some links explaining the getter/setters in JS 1.5:
http://ejohn.org/blog/javascript-getters-and-setters/
http://ajaxian.com/archives/getters-and-setters-in-javascript
Be aware though, they don't seem to be supported in IE, and some developers have (legitimate) concerns about the idea of variable assignment having side-effects.
get/set are not reserved keywords as Daniel points out. I had no problem creating a top-level functions called "get" and "set" and using the alongside the code-sample posted above. So I assume that the parser is smart enough to allow this. In fact, even the following seems to be legitimate (if confusing):
var Sample = {
bs : "",
get get() { return this.bs; },
set get(val) { this.bs = val; }
}
According to Mozilla, they are not in ECMAScript.
JavaScript Setters And Getters:
Usually the setter and getter methods follow the following syntax in JavaScript objects. An object is created with multiple properties. The setter method has one argument, while the getter method has no arguments. Both are functions.
For a given property that is already created within the object, the set method is typically an if/else statement that validates the input for any time that property is directly accessed and assigned later on via code, a.k.a. "set". This is often done by using an if (typeof [arg] === 'certain type of value, such as: number, string, or boolean') statement, then the code block usually assigns the this.(specific)property-name to the argument. (Occasionally with a message logging to the console.) But it doesn't need to return anything; it simply is setting the this.specific-property to evaluate to the argument. The else statement, however, almost always has a (error) message log to the console that prompts the user to enter a different value for the property's key-value that meets the if condition.
The getter method is the opposite, basically. It sets up a function, without any arguments, to "get", i.e. return a(nother) value/property when you call the specific-property that you just set. It "gets" you something different than what you would normally get in response to calling that object property.
The value of setters and getters can be easily seen for property key-values that you don't want to be able to be directly modified, unless certain conditions are met. For properties of this type, use the underscore to proceed the property name, and use a getter to allow you to be able to call the property without the underscore. Then use a setter to define the conditions by which the property's key-value can be accessed and assigned, a.k.a. "set". For example, I will include two basic setters and getters for this object's properties. Note: I use a constant variable because objects remain mutable (after creation).
const person = {
_name: 'Sean';
_age: 27;
set age(ageIn) {
if (typeof ageIn === 'number') {
this._age = ageIn;
}
else {
console.log(`${ageIn} is invalid for the age's key-value. Change ${ageIn} to/into a Number.`);
return 'Invalid Input.';
}
},
get age() {
return this._age;
},
set name(nameIn) {
if (typeof nameIn === 'string') {
this._name = nameIn;
} else {
console.log(`Change ${nameIn} to/into a(ny) String for the name's
key-value.`);
return 'Invalid Input.';
}
},
get name() {
return this._name;
}
};
Where it gets interesting is when you try to set/assign a new key-value for the _age property, because it has to meet the if conditional in order to be successfully assigned, meaning not all assignments are valid, etc.
person.age = 'twenty-eight'; /* output: twenty-eight is invalid for the
age's key-value. Change twenty-eight to/into a Number. */
console.log(person.age); // output: 27 (twenty-eight was never assigned)
person.age = 28; // output: none
console.log(person.age); // output: 28
Note how I was able to access the person._age property via the person.age property thanks to the getter method. Also, similar to how input for age was restricted to numbers, input for the name property is now restricted/set to strings only.
Hope this helps clear things up!
Additionally, some links for more:
https://johnresig.com/blog/javascript-getters-and-setters/
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get
https://www.infragistics.com/community/blogs/infragistics/archive/2017/09/19/easy-javascript-part-8-what-are-getters-and-setters.aspx