I have a JavaScript object, let's call it godObject, in a front-end project that I need to relocate to the server. I want to replace godObject with a proxy that will trap all accesses and forward them as HTTP calls. For properties on godObject, this is no problem. I can put put a Proxy around an empty object, and use a get trap, like this...
const godProxy = new Proxy({},{ get:(target, prop, receiver)=>{
// here I can trap all property accesses, without knowing in
// advance the names of the properties.
// You could imagine that functions would first be retrieved as
// properties, then invoked, but no.
})
For function invocations, this doesn't work because the apply trap needs to go on the function, not its container, so godProxy.someArbitraryInvocation() returns a xxx is not a function error. There is no way to trap and examine the invocation.
Is there a way to construct something that will trap any invocation of a member, without needing to know in advance the names of these members?
Related
When instance function are called in a class each instance of object get own copy of function but in prototype method and static method no copy is created , they belong to class, so if they both doesn't create a copy of their function, so why do we have static function if we can simply use prototype method if we don't want to copy??
I am a little bit confuse, if anyone can explain it will be a great help
In order to use a prototype/instance method, you need to either have an instance of an object or specifically access the type's .prototype. For methods that don't require an instance, a static method provides simpler syntax. Think of the String.fromCharCode() method as an example. It wouldn't make sense to say:
let str = "dummy string".fromCharCode(127);
The extra string instance there is just a distraction from what you're really trying to do:
let str = String.fromCharCode(127);
This applies good programming practices of reduced coupling (not requiring an instance in order to invoke a method that doesn't need it) and information hiding (by not exposing a method on instances of objects which doesn't pertain to those specific objects).
A static method does not exist on instances. Prototype methods do. So, if you want to call someArr.filter(x => x > 5) that would be an instance method that works on the given array.
An example of astatic method is Array.isArray(someArr). It makes very little sense to make the static method an instance method because you'd need an instance before calling it. That would lead to code like someArr.isArray(someArr) which is illogical - you need an array to check if something is an array. And that can very easily be fail spectacularly if someArr is not in fact an array:
const someArr = {
isArray() { return true; },
filter() { return "I am not an array"; },
};
console.log(someArr.isArray(someArr));
console.log(someArr.filter(x => x > 5));
Yes, that example is indeed highly illogical in order to highlight why it is weird. Assuming .isArray() was an instance method, you could create a new array in order to use it to call [].isArray(someArr). But that method does not require any instance data. The object created exists only to give you access to the method and is discarded immediately afterwards. That design is still not sensible.
Both static methods and prototype methods exist independent from any instances. The difference is that a prototype method expects to be called on an instance, i.e. to have an instance passed as the this argument, whereas the static method does not require an instance and expects none.
Even without placing them anywhere on the class, we can see this distinction in the following example:
function myStaticMethod(arg) {
console.log('Doing something with '+arg);
}
function myMethod(arg) {
console.log('Doing something with '+this+' and '+arg);
}
const myInstance = new MyClass();
myStaticMethod('value');
myMethod.call(myInstance, 'value');
Now the .call() syntax is not very ergonomic, we prefer myInstance.myMethod('value'), so that is why we place the method on the prototype object of the class, having it inherited by all instances.
For static methods, this is not necessary. They don't need an instance, we don't want to call them on an instance, we want to call them as MyClass.myStaticMethod('value') so that is where we place them. We could put them on the prototype as well, but that would lead to confusion (myInstance.myStaticMethod()), name collisions, and unncessarily long invocations (MyClass.prototype.myStaticMethod()). It's imaginable to write new MyClass().myStaticMethod(), but there you would unnecessarily create an instance that is not required (and it might not even be possible to create).
I tried googling but couldn't find a precise answer, so allow me to try and ask here. If the question does not seem proper, please let me know and I'll delete it.
In JS you've got three different way of writing certain build in functionalities:
str.length
str.toString()
parseInt(str)
I wonder if there is a reason behind these different ways of writing. As a new user I don't grasp why it couldn't be streamlined as: length(str) / toString(str) / parseInt(str) or with dot formulation.
I however think if I do know the reason behind these differences, it would give me a better understanding of JavaScript.
Length is one of the attributes of string in JavaScript. Hence you use string.length to get the length of the string.
toString is a function for string objects, hence we use stringobj.toString().
parsInt(str) is a global function which takes string as a parameter.
JavaScript is object-oriented, so there are functions or procedures which require first an object to use as this in their bodies. str.length is a property, both syntactically and semantically. It doesn't require any parameters and represents some quality of the object. obj.toString() is a method (a function attached to an object), which doesn't represent any characteristics of the object, but rather operates on its state, computes some new values, or changes the state of the object a lot. parseInt(str) is a "global" function, which represents an operation not attached to any type or object.
Under the hood, these three ways may be well implemented with just calling a function, passing this as the first parameter (like C# does, for example). The semantic difference is the important one.
So why not use just the third syntax, like for example PHP does? First, it doesn't bloat the global environment with lots of functions which only work for one specific case and type, allowing you to specify any new function you want without breaking the old functionality. Second, it ecourages you to use object-oriented concepts, because you can already see working objects and methods in the language, and can try to make something similar.
And why isn't parseInt a method? It can as well be str.toInt() without any issues, it's just the way JavaScript designers wanted it to be, although it seems also a bit logical to me to make it a static method Number.parseInt(str), because the behaviour of the function is relevant more to the Number type than the String type.
JavaScript is based around objects. Objects have properties (e.g. a User object may have name and age properties). These are what define the user and are related to the user. Properties are accessed via dot-notation or brackets notation (to access Eliott’s age, we’ll use either eliott.age or eliott['age'] — these are equivalent).
These properties can be of any type — String, Number, Object, you name it — even functions. Now the proper syntax to call a function in JS is to put round brackets: eliott.sayHello(). This snippet actually fetches Eliott’s sayHello property, and calls it right away.
You can see Eliott as a box of properties, some of which can be functions. They only exist within the box and have no meaning out of the box: what would age be? Whose age? Who’s saying hello?
Now some functions are defined at the global level: parseInt or isNaN for instance. These functions actually belong to the global box, named window (because legacy). You can also call them like that: window.parseInt(a, 10) or window.isNaN(a). Omitting window is allowed for brevity.
var eliott = {
name: 'Eliott',
age: 32,
sayHello: function () { console.log('Hello, I’m Eliott'); }
};
eliott.name; // access the `name` property
eliott.age; // access the `age` property
eliott.sayHello; // access the `sayHello` property
eliott.sayHello(); // access the `sayHello` property and calls the function
sayHello(eliott); // Reference error: `window.sayHello` is undefined!
Note: Some types (String, Number, Boolean, etc.) are not real objects but do have properties. That’s how you can fetch the length of a string ("hello".length) and reword stuff ("hello, Eliott".replace("Eliott", "Henry")).
Behaviour of these expressions is defined in ECMAScript grammar. You could read the specification to understand it thoroughly: ECMAScript2015 specification. However, as pointed out by Bergi, it's probably not the best resource for beginners because it doesn't explain anything, it just states how things are. Moreover I think it might be too difficult for you to be able to grasp concepts described in this specification because of the very formal language used.
Therefore I recommend to start with something way simpler, such as a very basic introduction to JavaScript: JavaScript Basics on MDN. MDN is a great resource.
But to answer your question just briefly:
str.length is accessing a property of the str object.
parseInt(str) is a function call
str.toString() is a call of a function which is a property of the str object. Such functions are usually named methods.
Functions and methods are in fact very similar but one of the differences (except for the obvious syntax difference) is that methods by default have context (this) set to refer to the object which they're part of. In this case inside of toString function this equals to str.
Note: Accessing a property (as in str.length) could in effect call a getter function but it depends on how the object is defined, and is in fact transparent for the user.
I'm working on a customization for Sugar Professional 7.2.x that pushes a filter from an auxiliary script into the filter function for the list view page. By setting a breakpoint inside the applyFilter function and exporting the function itself as a member of the global object, I can then call the function from my script and execute a temporary filter accordingly. So I know I have the correct syntax for execution, e.g:
window.exportedApplyFilter(null, {name:"Mr. Rogers"});
The hangup is that I can't get that applyFilter function in any other way, e.g.
App.view.layout.someMagicObject.applyFilter(...);
Is there a way to access that function from another script?
Thanks to the Sugar team, I have an answer to my question. The solution is to pry in through the controller.layout object tree:
App.controller.layout.getComponent('sidebar').getComponent('main-pane')
This allows one to drill down to any Sidecar UI component and access the controller functions associated therewith. Perhaps not as elegant as other solutions, but it's readable.
If I wanted to take this further, I might write a short function to recurse through the subtree and look for the element with the correct CID number, then return the full path to it. CID numbers are progressive and advance depth-first, so the search would be pretty fast. But a hand search in the browser dev console only took minutes. Once that's found, accessing it again is a matter of a chain of getComponent(...) calls. The final return from the chain should be the element wanted (filter control, in my case) and should have the desired method as well.
Suppose I have a function which returns an object :
getMyObject(){
//do stuff here
return object;
}
Is it bad practice to call a method (that doesn't return anything) on the function name itself:
getMyObject().method();
instead of assigning a variable to the return object and then calling the method on that variable :
var returnedObject = getMyObject();
returnedObject.method();
I am working with an html page that has many nested frames, and I have access to a function that returns one of these frames. The frame might be used several times within other functions in my script, and I was wondering if it would be ok for me to access the frame in the way asked above, or if it would be better to declare a global variable.
*EDIT: * Ahh I haven't gotten a chance to use jQuery. Good to know!
Yes, this is perfectly OK. jQuery for example uses this as well. It returns objects on which you can call methods immediatley. This is called chaining.
In your example, method chaining is the better practice IMHO. If a function returns an object, upon which you want to call a method, but you do not need to reference that object after calling that method, don't assign it to a variable.
Also, jQuery code does this all the time(1):
$('#foo').on('click',function(){});
/\ \\
|| \\
|| \\
function call returns jQ object <============|
\\ ||
\\call method "on" upon _||
(1)To clarify: I do not claim that all jQ methods return an object .attr() or .prop() don't. What I mean by "all the time" is actually that the scenario the OP describes is very common in jQ code (function call, invoke method on returned object):
var someString = $($('.foo').get(0)).attr('id');//tricky little bugger, this :)
var aBool = $('#foo').prop('checked');
Usually, no. Chaining method calls like that is usually simpler, more elegant, and easier to read. However, there are a few cases when it's better to use a variable.
If you use a method (or chain of methods) a lot of times, you can use a variable if it makes the code cleaner.
If the method takes a long time to process, it's better to cache the result. For example, if you have some method called calculateResults(), and it pulls data from a database, that takes some time. If the data doesn't change, you'll be incurring that cost for each call to the method. Better to store it in a variable and reuse it.
If the method has side effects, you should be careful about calling it more than once. Those side-effects will be inflicted each time you call it. Again, as an example, if you have a function like nextItem() that advances to the next item and returns it (a la Java iterators), then calling it more than intended will actually change the result. In this case, you have no choice but store the result, since calling it more than once will produce incorrect behavior.
Otherwise, chain away!
Original source: http://twitter.com/tobeytailor/status/8998006366
(x=[].reverse)() === window // true
I've noticed that this behavior affects all the native types. What exactly is happening here?
This is to do with the weird way this binding works in JavaScript.
[].reverse
is the method reverse on an empty list. If you call it, through one of:
[].reverse();
[]['reverse']();
([].reverse)();
then it executes with this bound to the list instance []. But if you detach it:
x= [].reverse;
x();
it executes with no this-binding, so this in the function points to the global (window) object, in one of JavaScript's worst, most misleading design mistakes.
(x=[].reverse)()
Is also doing the detach. The assignment operator returns the same function object it was passed so it looks like it's doing nothing, but it has the side-effect of breaking the limited special case that causes JavaScript to bind this.
So you are saying:
Array.prototype.reverse.call(window)
reverse, like many other Array.prototype methods, is defined by ECMAScript to work on any native sequence-like object. It reverses the items with number-string keys (up to object.length) and returns the object. So it'll return the object that was passed in for any type that has a length property.
window has a length property, which corresponds to window.frames.length, so calling this method with this pointing at window will work and return the window. In theory it may still fail, because:
window is allowed to be a “host object” rather than a “native object”; in this case the guarantees about what you can pass to other prototypes' methods don't necessarily apply; and
if the window actually has frames/iframes, it would try to reverse their order, which wouldn't work because the frame collection is read-only.
However, in current browsers the former case does work and the latter fails silently without an error, so you still get the ===window behaviour and not an Exception.