This question already has answers here:
Is there an equivalent of the __noSuchMethod__ feature for properties, or a way to implement it in JS?
(6 answers)
Closed 7 years ago.
I would like to override accessor of a javascript object so that instead of override it should return a fixed value.
eg.
var obj = {};
console.log(obj.someProperty) //will print undefined expected value false
If a property is undefined there is no way to have it return false by default but it will be "falsey".
For example:
var obj = {};
if (!obj.someProperty) {
console.log("expression is falsey");
}
A more explicit way to test truthiness is to use the double bang operator:
var obj = {};
console.log(!!obj.someProperty) // print's undefined, but evaluates to false
But in short, what you are going after will not work because in JavaScript you cannot redefine undefined.
I would do this with the following:
var obj = {};
if (!obj.hasOwnProperty('itdoesnthavethis')) console.log('property is not there')
This will always return a boolean and will not check through the object's prototype chain for the property, just the object itself.
Read more here : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
With ES6 and its Proxy feature you can do something like this:
var obj = {};
obj = new Proxy(obj, {
get: function(target, prop) {
var pv = target[prop];
return pv === undefined ? false : pv;
}
});
that will essentially create proxy wrapper around your object handling property get operations.
With ES5 something like that is impossible to achieve for an arbitrary property.
But if set of properties is known you can design your own object class:
function MyObject() {}
MyObject.prototype.foo = false;
MyObject.prototype.bar = false;
MyObject.prototype.baz = false;
and use it as:
var obj = new MyObject();
console.log(obj.foo); // false
console.log(obj.bar); // false
console.log(obj.foobar); // undefined
Related
This question already has answers here:
ES6 arrow function and lexical scope inside a function [duplicate]
(2 answers)
Closed 4 years ago.
How can I get the reference to what's being return to the method call? Like how we have the arguments variable to get all arguments being passed to a function. How can I get what's being returned to so I can chain a function?
let myFunc = function(obj, num){
if (typeof obj === 'number' && typeof num === 'undefined') {
num = obj;
obj = this;
}
console.log(obj.name);
console.log(num);
console.log(Object(this));
return obj;
};
let myObj = {
name: 'Devin',
};
myFunc(myObj, 1);
myObj.myFunc = myFunc;
myObj.myFunc(2).myFunc(3);
edit: It's written out this because it's currently used in many places that I will have to refactor down the road but do not have time to right now. So I'm trying to do a few changes that don't affect current code but will work the way I want moving forward. myFunc(myObj, 1) is current but I have done a minor refactor to inline like so... myObj.myFunc(myObj, 2).myFunc(myObj, 3) ... but I thought I could remove myObj as an argument since it's being returned.
edit 2: Changed arrow es6 function to using function keyword to keep this context and added console.log(Object(this)). But still getting undefined from myObj.name and Object(this) only gives the argument
ANSWER: The problem was that I was using an arrow function and that I had typeof num === 'number' instead of equal to 'undefined'. Thank you.
myFunc.bind(myObj) doesn't serve any good purpose because arrows cannot be bound. In order to use dynamic this it should be regular function, e.g. shorthand syntax:
let myObj = {
name: 'Devin',
myFunc(num) {
console.log(num);
return this;
}
};
myObj.myFunc(2).myFunc(3); // basically a noop
If you have an object attached to a property like so :
obj = {};
obj.prop = {name:'test'};
Is there a way, similar to using array.splice, to remove the object from that property, and return it so it can be attached to another object?
Sure you can:
var obj = {};
obj.prop = { name: 'test' };
var newObj = { prop: obj.prop} ; // Copy prop to a new object
delete obj.prop; // delete `prop` on the old object.
document.body.textContent = 'newObj: ' + JSON.stringify(newObj);
delete throws an error in strict mode if the property is an own non-configurable property (returns false in non-strict). It returns true in all other cases.
So, while there technically isn't a function like pop or splice that returns the removed property, it's trivial to work around that.
To delete/return a property from an object in one swoop, I think you need your own function for this. Something like:
function removeValue(obj, property) {
var prop = obj[property];
delete obj[property];
return prop;
}
This question already has answers here:
Self-references in object literals / initializers
(30 answers)
Closed 8 years ago.
How can I reference a property of an object when creating the object itself? Example below which doesn't work:
var object = {
prop1 : $(this).find('.foo');
prop2 : this.prop1.find('.bar');
}
You can use the new keyword with an anonymous function:
var $self = $(this);
var object = new function () {
this.prop1 = $self.find('.foo');
this.prop2 = this.prop1.find('.bar');
};
Technically that object will have a different constructor property than the object literal would, but that is unlikely to cause an issue for most use cases.
As a simple demonstration:
var obj = new function () {
this.x = 7;
this.y = this.x * 2;
};
console.log(obj); // Object {x: 7, y: 14}
You can't refer a property of the object which is not yet created. You can have a function which will be called after the creation of object. So then you can refer a property using this.
Like bellow:-
obj = {
a1:3,
a2:function(){return this.a1}
};
so calling obj.a2() will return 3 here.
Or if you don't want to call is like a function use Get
obj = {
a1:3,
get a2(){return this.a1}
};
obj.a2; //returns 3
Basically what get does It binds an object property to a function that will be called when that property is looked up.
This might be helpful
var obj = {
prop1 : $(this).find('.foo');
prop2 : function() { return this.prop2.find('.bar'); }
};
I assume you're interested in avoiding recalculating $(this).find('.foo'), in which case you could do something like:
var object = (function() {
var prop1 = $(this).find('.foo'),
prop2 = prop1.find('bar');
return {
prop1: prop1,
prop2: prop2
};
}.bind(this);
Does anyone have any example implementation of making individual object props readOnly/non-configurable? I mean primitive data types. Have tried using ES5 Object API, but hitting a brick wall.
I can't show code, because it's still at that "messy" phase, but basically I'm iterating through an outside object which, itself, holds numeruos objects. Those objects each hold various primitive data types. I have made the outer objects readOnly, non-config, etc, but can't figure out how to do likewise for individual props, the innermost props.
So, if outer.inner.prop === "Hello", I want to make that value readOnly.
Thanks!
UPDATE
I just figured this out, it was all in the for loop I was using to iterate over props. Now I've actually get data descriptors for the props, even the primitive ones. :) Thanks all!
You have to iterate through the inner object, since there is no way to deep-freeze an object using standard ES5 methods.
function deepFreeze(obj) {
Object.keys(obj).forEach(function (key) {
if (typeof obj[key] == 'object')
deepFreeze(obj[key]);
});
Object.freeze(obj);
}
Edit:
Also works for defineProperty if you don't want to freeze:
function deepWriteProtect(obj) {
Object.keys(obj).forEach(function (key) {
if (typeof obj[key] == 'object')
deepWriteProtect(obj[key]);
Object.defineProperty(obj, key, { writable: false });
});
}
I'm not 100% sure I understand your question correctly, but from what I gather you are asking for private variables. If so, that can be easily achieved using closures.
function myClass(){
var mySecretProperty = 10;
this.getMySecretProperty = function(){
return mySecretProperty;
}
this.changeMySecretProperty = function(s){
// whatever logic you need for a setter method
mySecretProperty = s;
}
}
var myObj = new MyClass();
myObj.changeMySecretProperty(120);
myObj.getMySecretProperty(); // will return 120
myObj.mySecretProperty // will return undefined
Would the following (ES5) example help? It creates an empty constructor, with a getter for property a (and no setter, so de facto a is read only):
var Obj = function(){};
Obj.prototype = {
get a() {return 5;}
}
var x = new Obj;
alert(x.a); //=> 5
x.a = 6; //=> TypeError: setting a property that has only a getter
Not using ES5 you can do
var Obj = function(){
var a = 5;
if (!Obj.prototype.getA) {
Obj.prototype.getA = {
toString: function() {
return a;
}
};
}
}
var y = new Obj;
alert(y.getA); //=> 5
But that is not 100% failsafe: Obj.prototype.getA can be overwritten.
Here is a jsfiddle showing how you can use ES5 getter/setter definitions to make a property of an object something that can only be fetched. The code looks like this:
var object = {
get x() {
return 17;
}, set x() {
alert("You cannot set x!");
}
};
Of course the getter could obtain the value of the property ("x") from anywhere, like a closure from a constructor or something. The point is that the setter simply does not change the value, so attempts to change it:
object.x = 100;
will not have any effect.
This question already has answers here:
How to display all methods of an object?
(11 answers)
Closed 3 years ago.
Is there a way to print all methods of an object in JavaScript?
Sure:
function getMethods(obj) {
var result = [];
for (var id in obj) {
try {
if (typeof(obj[id]) == "function") {
result.push(id + ": " + obj[id].toString());
}
} catch (err) {
result.push(id + ": inaccessible");
}
}
return result;
}
Using it:
alert(getMethods(document).join("\n"));
If you just want to look what is inside an object, you can print all object's keys. Some of them can be variables, some - methods.
The method is not very accurate, however it's really quick:
console.log(Object.keys(obj));
Here is an ES6 sample.
// Get the Object's methods names:
function getMethodsNames(obj = this) {
return Object.keys(obj)
.filter((key) => typeof obj[key] === 'function');
}
// Get the Object's methods (functions):
function getMethods(obj = this) {
return Object.keys(obj)
.filter((key) => typeof obj[key] === 'function')
.map((key) => obj[key]);
}
obj = this is an ES6 default parameter, you can pass in an Object or it will default to this.
Object.keys returns an Array of the Object's own enumerable properties.
Over the window Object it will return [..., 'localStorage', ...'location'].
(param) => ... is an ES6 arrow function, it's a shorthand for
function(param) {
return ...
}
with an implicit return.
Array.filter creates a new array with all elements that pass the test (typeof obj[key] === 'function').
Array.map creates a new array with the results of calling a provided function on every element in this array (return obj[key]).
Take a gander at this code:-
function writeLn(s)
{
//your code to write a line to stdout
WScript.Echo(s)
}
function Base() {}
Base.prototype.methodA = function() {}
Base.prototype.attribA = "hello"
var derived = new Base()
derived.methodB = function() {}
derived.attribB = "world";
function getMethods(obj)
{
var retVal = {}
for (var candidate in obj)
{
if (typeof(obj[candidate]) == "function")
retVal[candidate] = {func: obj[candidate], inherited: !obj.hasOwnProperty(candidate)}
}
return retVal
}
var result = getMethods(derived)
for (var name in result)
{
writeLn(name + " is " + (result[name].inherited ? "" : "not") + " inherited")
}
The getMethod function returns the set of methods along with whether the method is one that has been inherited from a prototype.
Note that if you intend to use this on objects that are supplied from the context such as browser/DOM object then it won't work IE.
From here:
Example 1: This example writes out all the properties of the "navigator" object, plus their values:
for (var myprop in navigator){
document.write(myprop+": "+navigator[myprop]+"<br>")
}
Just replace 'navigator' with whatever object you are interested in and you should be good to go.
As mentioned by Anthony in the comments section - This returns all attributes not just methods as the question asked for.
Oops! That'll teach me to try and answer a question in a language I don't know. Still, I think the code is useful - just not what was required.
Since methods in JavaScript are just properties that are functions, the for..in loop will enumerate them with an exception - it won't enumerate built-in methods. As far as I know, there is no way to enumerate built-in methods. And you can't declare your own methods or properties on an object that aren't enumerable this way.