I was reading on GitHub in petkaantonov/bluebird on Optimization killers. And when reaching chapter 3.3 what-is-safe-arguments-usage specifically the part What is safe arguments usage? I realized that I might be going wrong using bind and apply in my project.
The post states:
Be aware that adding properties to functions (e.g. fn.$inject =...) and bound functions (i.e. the result of Function#bind) generate hidden classes and, therefore, are not safe when using #apply.
I used this answer on the question Use of .apply() with 'new' operator. Is this possible? to be able to pass an array of arguments to my constructor function like this:
new (Cls.bind.apply(Cls, arguments))();
This looks suspiciously much like what is described as not safe in the post.
Is this true? Am I going wrong here?
I would simply like to understand if the issue in the post applies to this example case, especially because it might be useful to comment on the answer so others don't make the same error (the post is heavily upvoted so it seems people are using this solution a lot).
Note: I recently found out about the spread operator (awesome) which is a nice alternative, to my previous solution:
new Cls(...arguments);
Related
Assuming I have an external javascript inserted in the page and it exports a few things to the external scope (ie binds them to window).
I want to call some of those properties in my typescript projects as:
UndeclaredExportedProperty.aFunction()
But typescript will not allow me to compile that ><
I don't want to go through a convoluted way of declaring the whole interface of the module since I don't know it and quite frankly I don't care about it. Its just a module that I have to call once and "trust" that by the time I make the call its loaded and contains the correct elements (its non critical so not calling it will not make the world catch fire).
What is the easiest way of doing this with typescript ?
Edit in response to mark as duplicate:
Whilst the answer to that question did solve my problem the question is different (for example stack isn't able to find it as a duplicate suggestion) and I feel like for what I'm trying to do Pokus answer is a more straight forward and general solutions than the answers in that question
That being said, if an admin feels like this is still a duplicate or to simple of a question feel free to delete/close since I've gotten my answer. Personally I will leave it standing because the next person searching via google or so might find an answer more easily this way.
You should use the declare keyword for that:
declare var UndeclaredExportedProperty: any;
The official docs states this here:
https://www.typescriptlang.org/docs/handbook/modules.html in the section
Working with Other JavaScript Libraries
Try
(window as any).UndeclaredExportedProperty.aFunction()
this will tell the compiler to temporarily treat the Window instance as untyped and allow you to do anything with it.
Ok, this question was apparently answered here:
How do you explicitly set a new property on `window` in TypeScript?
I can't mark my own post as a duplicate so I will just leave this here and close the thread, maybe the next poor sod to google search and not click that link will stumble upon this.
Apparently properties of an object (e.g window) can be queried with the array selection operator (o.o?) so you can just do:
window["UndeclaredExportedProperty"].aFunction()
I have seen a lot of discussion regarding extending Element. As far as I can tell, these are the main issues:
It may conflict with other libraries,
It adds undocumented features to DOM routines,
It doesn’t work with legacy IE, and
It may conflict with future changes.
Given a project which references no other libraries, documents changes, and doesn’t give a damn for historical browsers:
Is there any technical reason not to extend the Element prototype. Here is an example of how this is useful:
Element.prototype.toggleAttribute=function(attribute,value) {
if(value===undefined) value=true;
if(this.hasAttribute(attribute)) this.removeAttribute(attribute);
else this.addAttribute(attribute,value);
};
I’ve seen too many comments about the evils of extending prototypes without offering a reasonable explanation.
Note 1: The above example is possibly too obvious, as toggleAttribute is the sort of method which might be added in the future. For discussion, imagine that it’s called manngoToggleAttribute.
Note 2: I have removed a test for whether the method already exists. Even if such a method already exists, it is more predictable to override it. In any case, I am assuming that the point here is that the method has not yet been defined, let alone implemented. That is the point here.
Note 3: I see that there is now a standard method called toggleAttribute which doesn’t behave exactly the same. With modification, the above would be a simple polyfill. This doesn’t change the point of the question.
Is it ok? Technically yes. Should you extend native APIs? As a rule of thumb no. Unfortunately the answer is more complex. If you are writing a large framework like Ember or Angular it may be a good idea to do so because your consumers will have Benifits if better API convenience. But if you're only doing this for yourself then the rule of thumb is no.
The reasoning is that doing so destabilizes the trust of that object. In other words by adding, changing, modifying a native object it no longer follows the well understood and documented behavior that anyone else (including your future self) will expect.
This style hides implementation that can go unnoticed. What is this new method?, Is it a secret browser thing?, what does it do?, Found a bug do I report this to Google or Microsoft now?. A bit exaggerated but the point is that the truth of an API has now changed and it is unexpected in this one off case. It makes maintainability need extra thought and understanding that would not be so if you just used your own function or wrapper object. It also makes changes harder.
Relevant post: Extending builtin natives. Evil or not?
Instead of trying to muck someone else's (or standard) code just use your own.
function toggleAttribute(el, attribute, value) {
var _value = (value == null ? true : value;
if (el.hasAttribute(attribute)) {
el.removeAttribute(attribute);
} else {
el.addAttribute(attribute, _value);
}
};
Now it is safe, composible, portable, and maintainable. Plus other developers (including your future self) won't scratch their heads confused where this magical method that is not documented in any standard or JS API came from.
Do not modify objects you don't own.
Imagine a future standard defines Element.prototype.toggleAttribute. Your code checks if it has a truthy value before assigning your function. So you could end up with the future native function, which may behave differently than what you expected.
Even more, just reading Element.prototype.toggleAttribute might call a getter, which could run some code with undesired sideways effects. For example, see what happens when you get Element.prototype.id.
You could skip the check and assign your function directly. But that could run a setter, with some undesired sideways effects, and your function wouldn't be assigned as the property.
You could use a property definition instead of a property assignment. That should be safer... unless Element.prototype has some special [[DefineOwnProperty]] internal method (e.g. is a proxy).
It might fail in lots of ways. Don't do this.
In my assessment: no
Massive overwriting Element.prototype slow down performance and can conflict with standardization, but a technical reason does not exist.
I'm using several Element.prototype custom methods.
so far so good until I observe a weird behaviour.
<!DOCTYPE html >
<html >
<body>
<script>
function doThis( ){
alert('window');
}
HTMLElement.prototype.doThis = function( ){
alert('HTMLElement.prototype');
}
</script>
<button onclick="doThis( )" >Do this</button>
</body>
</html>
when button is clicked, the prototype method is executed instead of the global one.
The browser seems to assume this.doThis() which is weird. To overcome, I have to use window.doThis() in the onclick.
It might be better if w3c can come with with diff syntax for calling native/custom methods e.g.
myElem.toggleAttribute() // call native method
myElem->toggleAttribute() // call custom method
Is there any technical reason not to extend the Element prototype.
Absolutely none!
pardon me:
ABSOLUTELY NONE!
In addition
the .__proto__, was practically an a illegal (Mozilla) prototype extension until yesterday. - Today, it's a Standard.
p.s.: You should avoid the use of if(!Element.prototype.toggleAttribute) syntax by any means, the if("toggleAttribute" in Element.prototype) will do.
In the socket.io documentation, they use a nomenclature that doesn't look like javascript (though it's a javascript library) that seems a bit out of place.
Examples here: http://socket.io/docs/client-api/ (the page has changed since, here's a web archive snapshot as of 2014)
This one is clear enough (just specifying types of arguments and return value):
IO(url:String, opts:Object):Socket
But this style I don't recognize at all:
IO#protocol
Manager#timeout(v:Boolean):Manager
I can pretty much figure it out through deduction (though I find it hard to read because it looks so foreign), but where does this style come from and why? Is this from another language (it certainly isn't javascript syntax that I've ever seen)? Is there a name for it? Is there a description of this style of documenting objects, methods, properties?
FYI, the idea to ask this question came because I referred a user here on SO to the socket.io documentation and they came back and said that wasn't javascript, did I have a link to the javascript documentation. I had to explain that it was the javascript documentation, it was just a funky (non-javascript-like) documentation style.
The page in question has been rewritten since to use object.property instead, but I remember that Object#property style, though I don't think it's ever had a name.
The problem it's trying to solve is that properties/methods can be available on constructors like Array.isArray(), as well as on instances, like ['foo','bar'].join(' '). The question is how to denote the latter. There were some competing denotations, such as
array.join(), which is what the socket.io docs are using now
Array.prototype.join (technically correct, but arguably even more confusing than Array#join to anyone who doesn't know how prototypes work in JS)
Array#join(), invented to be clearly different from Array.join syntax, and to avoid confusion with any existing JavaScript syntax.
The Object#prototype syntax was somewhat popular ten years ago, but didn't win in the end, so now it's just confusing when you encounter it.
Underscore.js defines aliases for functions like _.each (alias: forEach) and _.map (alias: collect) and I don't understand why.
I initially thought this was to avoid issues with browsers that didn't implement those functions natively, my thinking was that calling [].map() would throw an error in IE7 and 8 because they didn't implement it natively but found that there was no issue since Underscore already defines those.
Then I thought it could have something to do with conflicts with other JS libraries like Prototype that implement similarly named functions but then realised that having an alias doesn't actually make a difference in the case of _.map since prototype implements .map and .colelct and actually I'd been using prototype's implementation all along (eg. this.collection.collect(...)).
So far it doesn't seem to have made any difference and it hasn't created any issues but I'd really like to know why this is happening.
I guess the purpose of aliases is to make the library more familiar for programmers with different backgrounds (eg, collect and include are used in Ruby, fold in functional languages etc).
Also, aliases can improve readability in some cases, for example
list.select(...).reject(...)
"sounds" better than
list.filter(...).reject(...)
If you look at their documentation, you will find it pretty close to lodash library (http://lodash.com/), and jQuery's library, and also Backbone and Ruby (found in the home page).
My guess, is that both of them are made to do the same thing, one in Server (Lodash), other in Client (Underscore), and to use the same syntax, they have some methods aliases.
Also, adding some aliases is never good, since it decreases errors when writing in multiple languages.
This question is similar to Why are methods in Ruby documentation preceded by a hash sign?
I understand why in Ruby instance methods are proceeded with a pound sign, helping to differentiate talking about SomeClass#someMethod from SomeObject.someMethod and allowing rdoc to work. And I understand that the authors of PrototypeJS admire Ruby (with good reason) and so they use the hash mark convention in their documentation.
My question is: is this a standard practice amongst JavaScript developers or is it just Prototype developers who do this?
Asked another way, is it proper for me to refer to instance methods in comments/documentation as SomeClass#someMethod? Or should my documentation refer to ``SomeClass.someMethod`?
No, I have not yet met another JavaScript project that uses this notation.
Something like this is useful in JavaScript, though, because unlike in many languages Class.methodName would refer to classmethods like String.fromCharCode, not instance methods which is what you are more often talking about. The method invoked by myinstance.methodName would be not MyClass.methodName but MyClass.prototype.methodName, and MyClass.prototype is an annoyance to keep typing.
(The standard JS library confuses this by making many instance methods also have a corresponding classmethod. But they're different functions.)
is it proepr for me to refer to instance methods in comments/documentation as SomeClass#someMethod?
Do what you like/find most readable. There's no standard here.
I think it comes from javadoc.
http://java.sun.com/j2se/1.5.0/docs/tooldocs/windows/javadoc.html#{#link}