I've been writing d3 code that ends up having lots of functions like this:
selection.attr('x', function(d) { return d.layout.x; });
Is there any way to simulate Scala's placeholder syntax, which would allow me to write this:
selection.attr('x', _.layout.x);
Obviously getters need to be told a specific parameter name to apply to, or one could define a sort of 'meta-getter' that responds with an anonymous function that gets the desired named attribute.
I'd be interested to know if anything like this exists in, for example, CoffeeScript. ES6 lambda functions are closer, but still not as semantic and clear as placeholder syntax.
You don't say what environment you want this to run in, so, assuming that the bleeding edge is okay, let's use Proxy:
var _ = new Proxy({}, {
get: function(target, name) {
return createProxyForPath(name, []);
}
});
function createProxyForPath(name, path) {
var newPath = path.slice();
newPath.push(name);
return new Proxy({}, {
get: function(target, name) {
if (name !== "$") return createProxyForPath(name, newPath);
return function getter(obj) {
return newPath.reduce(function(prev, curr) {
return prev[curr];
}, obj);
};
},
apply: function(target, context, args) {
// TODO: Preserve function calls and args here
}
});
}
You would use it like this:
> [{x: 1}, {x: 2}, {x: 3}].map(_.x.$)
[1, 2, 3]
It's not a complete replacement for Scala's magic underscore (it doesn't trap method calls right now, for example, so you can't do _.x.toString().slice(0, 3) to take one example). Also, it requires an explicit $ to signal the end of the chain. But for simple getters it works pretty well.
Alternately, if you need to support browsers that aren't Firefox right now you could write a sweet.js macro to generate the getter instead:
// Via Daniel
macro _ {
rule { . $m ... } => { function (value) { return value.$m ... } }
}
selection.attr('x', _.layout.x + 1);
Will expand to:
selection.attr('x', function(value) {
return value.layout.x + 1;
});
(If you use value yourself in the function sweet.js will do the right thing and rename the argument to value$some-integer to avoid any name conflicts inside the anonymous function.)
It does handle method calls, but of course none of these approaches handle using the placeholder as, for example, a function argument:
selection.attr('x', someFunction(_));
This could be emulated with a function instead of an object:
var getter = function(properties) {
props = properties.split('.');
return function(d) {
return props.reduce(function(prev, curr) {
return prev[curr];
}, d);
};
};
selection.attr('x', getter('layout.x'));
Which is... okay, but I wonder if JS can do better.
Related
I am using a proxy to handle the creation of an object without have to declare all "parent key" of the object.
var target = {};
var config = Proxy_ObjectCreator(target, handlers);
config.foo.bar = "Didn't need to create foo !";
return target;
Instead of this
var config = {
foo : {
bar : "needed to create foo ..."
}
};
return config;
That part is fine and functional, but the issue I'm having is that it often happens that I forget that I need to return the target object instead of the proxy, which often creates really strange behaviors in my code.
For what I am aware of, there is no way for a Proxy object to handle the return statement. And so I'm trying to find a way to do exactly that. Something like that:
var config = Proxy_ObjectCreator({}, {
get: (obj, prop, receiver) => {
//Do stuff ...
},
set: (obj, prop, receiver) => {
//Do stuff ...
},
return: () => {
return this.target;
}
});
config.foo.bar = "Didn't need to create a target obj and don't need to return it !";
return config;
Is there anyway to achieve that ?
Thanks you.
Edit
I'm using that to override configurations from a larger product to the client's specifications. So I'm working with hundreds of lines of configurations. Using a proxy allows me to structure the configuration file for future and clearer reading. It also allows me to group configuration's that can be all over the original config file together to comment on the reason why they are changed, without having to scroll up and down the object.
//Normal Object Case
function getClientConfigs() = {
return {
config1: {
foo: {
bar: {
foofoo: {
barbar: "value to override"
}
}
}
},
// hundreds of other configs
config2:{
foo: "other value to override"
}
};
}
//With proxy
function getClientConfigs() = {
var config = {};
var proxy = Proxy_ObjectCreator(config, handlers);
// Changing because client wanted that for x reason
proxy.config1.foo.bar.foofoo.barbar = "value to override";
proxy.config2.foo = "other value to override";
return config;
}
$.extend(originalConfig, getClientConfigs());
No, there is no way to get the proxy recognise when it is returned from a function. (Btw, it also is returned from your Proxy_ObjectCreator function, so you'd need to explicitly ignore that…). No, that would get way too complicated.
But you could use a different design pattern - don't make Proxy_ObjectCreator a factory function, instead give it a callback so that the proxy cannot (easily) escape from the context:
function getClientConfigs() = {
return withProxiedCreation({}, proxy => {
proxy.config1.foo.bar.foofoo.barbar = "value to override";
proxy.config2.foo = "other value to override";
});
}
function withProxiedCreation(target, callback) {
var proxy = new Proxy(target, handlers);
callback(proxy);
return target;
}
I've created a Javascript object with a layout like this:
var myObject : {
doSomething : function (args) {
//do some stuff
return result;
}
//note the args for both functions are of the same format
doSomethingElse : function (args){
//do some other stuff
return otherResult
}
}
Now I want to achieve the following, but am not sure on how to do it in a clean way:
console.log(myObject(args));
/*
Output:
{
doSomething : result,
doSomethingElse : otherResult
}
*/
I'd like to keep both functions separate, as I would like to be able to refer to them in separate instances, but also evaluate both at once to get the desired output as above.
Thanks in advance for your help!
I'd imagine you'd have to iterate, something like:
var results = {},
args = "some args";
for (var key in myObject) {
if (typeof myObject[key] === "function") results[key] = myObject[key](args);
}
console.log(results); //should be the output you want (untested)
Add one more method that calls both methods (passing them the arguments) and returns your desired object output. Something like this would do:
...
doBoth: function (args) {
return {
doSomething: this.doSomething(args),
doSomethingElse: this.doSomethingElse(args)
};
}
...
Calling myObject.doBoth(args) will return the result you hoped for.
jsFiddle Demo
You can also do something a bit more advanced, for example listing the method names you expect to be run for the result:
...
doThese: function (methods, args) {
var result = {};
methods.forEach(function (m) {
result[m] = this[m](args);
}, this);
return result;
}
...
You could invoke this with myObject.doThese(['doSomething', 'doSomethingElse'], args).
jsFiddle Demo
I would advise you not to run all the methods on the object (like other answers suggest). Seems easier at first, but will make your object difficult to modify and cause unintended behaviour in the future.
var BigObject = (function() {
function deepCalculate(a, b, c) {
return a + b + c;
}
function calculate(x) {
deepCalculate(x, x, x);
}
return {
calculate: calculate,
api: {
deepCalculate: deepCalculate
}
}
})();
This is basic self executing function with private function I keep in api.
The problem I have is that now I can't overwrite deepCalculate from the outside of the function.
How is that a problem? I use Jasmine and want to test if function was called. For example:
spyOn(BigObject, 'calculate').andCallThrough();
expect(BigObject.api.deepCalculate).toHaveBeenCalled();
fails. However as I debug, I am sure that Jasmine binds BigObject.api.deepCalculate as a spy, however from the inside calculate still calls original deepCalculate function and not the spy.
I would like to know how can I overwrite the function and not just a reference for it.
The simple answer would be:
(function ()
{
var overWriteMe = function(foo)
{
return foo++;
},
overWrite = function(newFunc)
{
for (var p io returnVal)
{
if (returnVal[p] === overWriteMe)
{//update references
returnVal[p] = newFunc;
break;
}
}
overWriteMe = newFunc;//overwrite closure reference
},
returnVal = {
overWrite: overWrite,
myFunc: overWriteMe
};
}());
Though I must say that, I'd seriously think about alternative ways to acchieve whatever it is you're trying to do. A closure, IMO, should be treated as a whole. Replacing parts of it willy-nilly will soon prove to be a nightmare: you don't know what the closure function will be at any given point in time, where it was changed, what the previous state was, and why it was changed.
A temporary sollution might just be this:
var foo = (function()
{
var calc = function(x, callback)
{
callback = callback || defaultCall;
return callback.apply(this, [x]);
},
defaultCall(a)
{
return a*a+1;
},
return {calc: calc};
}());
foo(2);//returns 5
foo(2,function(x){ return --x;});//returns 1
foo(2);//returns 5 again
IMO, this is a lot safer, as it allows you to choose a different "internal" function to be used once, without changing the core behaviour of the code.
This is what I have so far: http://jsfiddle.net/beCVL/5/
This is how I'm trying to override the default cloneNode:
Object.defineProperty(Object.prototype, "cloneNode", {
get: cloneNode2,
set: cloneNode2
});
but it's not working, so, I think Object.prototype doesn't have cloneNode, but Element.prototype doesn't either.
So, which class do I need to use to override cloneNode, assuming my method is correct?
It's a property of Node.prototype https://developer.mozilla.org/En/DOM/Node.cloneNode
Node.prototype.cloneNode = function() {}
However, modifying built in objects may give you grief in the future. If possible, you should create a different function and use that instead, that way, existing code that uses cloneNode won't break.
Try using:
Node.prototype.cloneNode = cloneNode2;
Object.defineProperty is not used for this purpose. Here's an example of a use for it:
var o = {};
Object.defineProperty(o, 'blah', {
'get': function () { return 'asdf'; },
'set': function (x) { alert(x); }
});
alert(o.blah); // alerts 'asdf'
o.blah = 'fdsa'; // alerts 'fdsa'
Apparently, this only works in Chrome.
To solve the actual problem, it should be simple enough to just replace the RGB codes with its equivalent hex code.
function decToHex(a) {
return ('00' + (+a).toString(16)).substr(-2);
}
function replaceRGB(str) {
return str.replace(/rgb\((\d{1,3}), (\d{1,3}), (\d{1,3})\)/, function (_, r, g, b) {
return "#" + decToHex(r) + decToHex(g) + decToHex(b);
});
}
replaceRGB("color: rgb(255, 0, 0)") // "color: #ff0000"
This series of fiddles is a work in progress, but it reimplements cloneNode's functionality. http://jsfiddle.net/beCVL/19/
as of April 4th, 10:53am EST, it needs to work with IE, as IE doesn't have a Node object.
Note, that in IE, prototype functions can't be overridden. So, all instances of cloneNode have to be replaced by a function that determines which version of cloneNode to use.
I have a function, a(), that I want to override, but also have the original a() be performed in an order depending on the context. For example, sometimes when I'm generating a page I'll want to override like this:
function a() {
new_code();
original_a();
}
and sometimes like this:
function a() {
original_a();
other_new_code();
}
How do I get that original_a() from within the over-riding a()? Is it even possible?
Please don't suggest alternatives to over-riding in this way, I know of many. I'm asking about this way specifically.
You could do something like this:
var a = (function() {
var original_a = a;
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})();
Declaring original_a inside an anonymous function keeps it from cluttering the global namespace, but it's available in the inner functions.
Like Nerdmaster mentioned in the comments, be sure to include the () at the end. You want to call the outer function and store the result (one of the two inner functions) in a, not store the outer function itself in a.
The Proxy pattern might help you:
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log( this, arguments );
return proxied.apply( this, arguments );
};
})();
The above wraps its code in a function to hide the "proxied"-variable. It saves jQuery's setArray-method in a closure and overwrites it. The proxy then logs all calls to the method and delegates the call to the original. Using apply(this, arguments) guarantees that the caller won't be able to notice the difference between the original and the proxied method.
Thanks guys the proxy pattern really helped.....Actually I wanted to call a global function foo..
In certain pages i need do to some checks. So I did the following.
//Saving the original func
var org_foo = window.foo;
//Assigning proxy fucnc
window.foo = function(args){
//Performing checks
if(checkCondition(args)){
//Calling original funcs
org_foo(args);
}
};
Thnx this really helped me out
You can override a function using a construct like:
function override(f, g) {
return function() {
return g(f);
};
}
For example:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a(); }
else { original_a(); other_new_code(); }
});
Edit: Fixed a typo.
Passing arbitrary arguments:
a = override(a, function(original_a) {
if (condition) { new_code(); original_a.apply(this, arguments) ; }
else { original_a.apply(this, arguments); other_new_code(); }
});
The answer that #Matthew Crumley provides is making use of the immediately invoked function expressions, to close the older 'a' function into the execution context of the returned function. I think this was the best answer, but personally, I would prefer passing the function 'a' as an argument to IIFE. I think it is more understandable.
var a = (function(original_a) {
if (condition) {
return function() {
new_code();
original_a();
}
} else {
return function() {
original_a();
other_new_code();
}
}
})(a);
The examples above don't correctly apply this or pass arguments correctly to the function override. Underscore _.wrap() wraps existing functions, applies this and passes arguments correctly. See: http://underscorejs.org/#wrap
In my opinion the top answers are not readable/maintainable, and the other answers do not properly bind context. Here's a readable solution using ES6 syntax to solve both these problems.
const orginial = someObject.foo;
someObject.foo = function() {
if (condition) orginial.bind(this)(...arguments);
};
I had some code written by someone else and wanted to add a line to a function which i could not find in the code. So as a workaround I wanted to override it.
None of the solutions worked for me though.
Here is what worked in my case:
if (typeof originalFunction === "undefined") {
originalFunction = targetFunction;
targetFunction = function(x, y) {
//Your code
originalFunction(a, b);
//Your Code
};
}
I've created a small helper for a similar scenario because I often needed to override functions from several libraries. This helper accepts a "namespace" (the function container), the function name, and the overriding function. It will replace the original function in the referred namespace with the new one.
The new function accepts the original function as the first argument, and the original functions arguments as the rest. It will preserve the context everytime. It supports void and non-void functions as well.
function overrideFunction(namespace, baseFuncName, func) {
var originalFn = namespace[baseFuncName];
namespace[baseFuncName] = function () {
return func.apply(this, [originalFn.bind(this)].concat(Array.prototype.slice.call(arguments, 0)));
};
}
Usage for example with Bootstrap:
overrideFunction($.fn.popover.Constructor.prototype, 'leave', function(baseFn, obj) {
// ... do stuff before base call
baseFn(obj);
// ... do stuff after base call
});
I didn't create any performance tests though. It can possibly add some unwanted overhead which can or cannot be a big deal, depending on scenarios.
So my answer ended up being a solution that allows me to use the _this variable pointing to the original object.
I create a new instance of a "Square" however I hated the way the "Square" generated it's size. I thought it should follow my specific needs. However in order to do so I needed the square to have an updated "GetSize" function with the internals of that function calling other functions already existing in the square such as this.height, this.GetVolume(). But in order to do so I needed to do this without any crazy hacks. So here is my solution.
Some other Object initializer or helper function.
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(
this.viewerContainer)
var viewer = this.viewer;
viewer.updateToolbarButtons = this.updateToolbarButtons(viewer);
Function in the other object.
updateToolbarButtons = function(viewer) {
var _viewer = viewer;
return function(width, height){
blah blah black sheep I can refer to this.anything();
}
};
Not sure if it'll work in all circumstances, but in our case, we were trying to override the describe function in Jest so that we can parse the name and skip the whole describe block if it met some criteria.
Here's what worked for us:
function describe( name, callback ) {
if ( name.includes( "skip" ) )
return this.describe.skip( name, callback );
else
return this.describe( name, callback );
}
Two things that are critical here:
We don't use an arrow function () =>.
Arrow functions change the reference to this and we need that to be the file's this.
The use of this.describe and this.describe.skip instead of just describe and describe.skip.
Again, not sure it's of value to anybody but we originally tried to get away with Matthew Crumley's excellent answer but needed to make our method a function and accept params in order to parse them in the conditional.