So the question is simply, if it's safe (wise) to declare method called "delete" in JavaScript. Example:
var request = {
delete : function (url) {
// Some code...
}
}
request.delete('http://page.dev/users/1');
I've tested this in Firefox and it's functional, but just wondering if it could cause problems in some other browsers; or in general if is it a good practice.
According to the language specification:
Identifier Names are tokens that are interpreted according to the grammar given in the “Identifiers” section of chapter 5 of the Unicode standard, with some small modifications. An Identifier is an IdentifierName that is not a ReservedWord (see 7.6.1).
This means you cannot use delete as a variable or function name, but you can use it as an object property name. This was not the case in the previous version of the specification, which is why most other answers are recommending you avoid using reserved words entirely. However, in ES5-compliant implementations, there should be no problem.
You'll never have an issue if you use this['style'], but with this.style, you should avoid reserved words, which does includes delete. According to the spec, it's actually OK to use reserved words as property names, but I would avoid it anyway because there are some bad implementations around (also it just has a generally bad feel to use reserved words, whatever the context).
No it's not a good idea because delete is a keyword. In the newest versions, they restricted the places where it will cause problems but there still are some.
One way of avoiding any kind of problem would be to use:
var request = {
"delete" : function (url) {
// Some code...
}
}
request["delete"]('http://page.dev/users/1');
But that's probably a bit less optimized and it's kind of ugly. I'd go with another name such as "remove".
delete is in the JavaScript reserved words list, use at your own peril.
delete object.property
delete object['property']
I'd use different keyword as other suggested - you can use synonyms like remove or purge - you get the idea.
But more important - make sure you're doing server-side validation for legibility of the call. Otherwise anybody could construct a delete call using "http://page.dev/users/1"
You should note that even using the bracket syntax for accessing properties isn't safe on all browsers.
Internet Explorer 7 and 8 will crash anyway.
Related
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 can't reconcile the following with any of the JavaScript documentation I've read. Can somebody please shed some light?
The following snippet is taken from file panelUI.js in the Mozilla repository.
const PanelUI = {
/** Panel events that we listen for. **/
get kEvents() ["popupshowing", "popupshown", "popuphiding", "popuphidden"],
// more properties...
_addEventListeners: function() {
for (let event of this.kEvents) {
this.panel.addEventListener(event, this);
}
// more code...
},
// more properties...
Everything I've read about JS defines a getter as essentially a function (or "a method that gets the value of a specific property" and "The get syntax binds an object property to a function that will be called when that property is looked up"), so I'm a bit baffled to see an array literal where I would expect to find the body of function kEvents().
What does it mean in JS to have a function name followed by an array literal (in general or as part of a get definition)?
How would you write code that is functionally equivalent to the above, but does not use this somehow odd syntax?
I assume this is a consequence of SpiderMonkey's non-standard and deprecated support for expression closures.
this isn't valid JavaScript in any way... unless Firefox is allowing it as an alternative syntax for some reason.
but if you tried to run this or similar code in a browser like chrome, or even trying to compile it using Babel and ES6, it fails.
How would you write code that is functionally equivalent to the above, but does not use this somehow odd syntax?
An "equivalent" syntax appears to be to wrap the data in curly braces and return it:
get kEvents() {
return ["popupshowing", "popupshown", "popuphiding", "popuphidden"];
},
I would guess that the example code returns the same array instance every time, whereas my code is going to generate a new array every time it's called.
I imagine that the listed line is a non-standard syntax that mozilla has implemented but that is not associated with any current spec. Oftentimes with these sorts of features the browser development community pushes a browser to implement a new feature to see if it's worthwhile for standardization. It could have been a proposed syntax that was later dropped as well
That all said, this is speculative, as I've never seen a standard with that syntax in it.
Can a reserved word be used as an object's property name?
This issue was raised indirectly in a previous Stack Overflow question: Browser support for using a reserved word as a property name in JavaScript. The answer seemed general consensus by Alex Wayne:
You can use those words, but only as strings and not shorthand
properties.
foo['class']; // cool
foo.class; // not cool
While I think that they are probably more knowledgeable than me in this area and it is probably a bad idea to use reserved words in some situations, I think their conclusion is wrong based on two points:
testing of the reserved words using them as a "shorthand" properties
the HTMLFormElement makes it impossible not to use reserved words in "shorthand"
First, using the reserved word list, each was added as a property to an Object and HTMLElement, both as obj["word"] and obj.word, and then retrieved as obj["word"] and obj.word. In each of the 63 cases all eight tests worked correctly.
Second, the HTMLFormElement necessitates this works because it retrieves in its elements using shorthand notation. If <input name='typeof' value='scalar' /> is an element of a form, then form.typeof == "scalar".
From my experience, reserved words are usually data inflicted (e.g. a column named "private"), not program inflicted. As such they contaminate JSON objects, and from there input, and from there the HTMLFormElement. Simply put, without a huge amount of (IMHO unnecessary) work, it's impossible to keep reserved words not being forced to work correctly in shorthand.
It seems to me these real problems:
care needs to be taken not to conflict with existent properties, not reserved words
(many if not all) variables cannot be reserved words
use of reserved words as properties can be (but are not necessarily) confusing
Is this conclusion correct then, that reserved words as property names, and accessing them either as strings or shorthand, is just fine - as long as a little common sense is applied to the situation?
In ECMAScript, starting from ES5, reserved words may be used as object property names "in the buff". This means that they don't need to be "clothed" in quotes when defining object literals, and they can be dereferenced (for accessing, assigning, and deleting) on objects without having to use square bracket indexing notation.
That said, reserved words may still NOT be used as identifier names. This is stated quite unambiguously in the spec and is stated somewhat emphatically here (if you don't want your eyes to bleed by having to read the actual language spec)...
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Reserved_Words
The following are keywords and may not be used as variables,
functions, methods, or object identifiers, because ECMAScript
specifies special behavior for them:
I'm not quite sure what the point is you want to make, so the only answer I can give is: Yes, it's ok to use reserved words as property names.
(However two small remarks: foo["class"] is ok, not foo[class]. And any way you should be using form.elements["xyz"] and not form.xyz to access an element named xyz.)
Yes, it can be used.
Just small remark, if you use YUI compressor you have to put property name which is equal to one of js reserved words in quotes.
For example, this won't compress
var a = { case : "foo"}; // syntax error, "invalid property id"
a.for = "bar"; // syntax error, "missing name after . operator"
This will do
var a = { "case" : "foo"}; //OK
a["for"] = "bar"; //OK
Here is Online JavaScript/CSS Compression Using YUI Compressor where this can be tested.
Yes, in most browsers (including IE9+)
There's actually an entry in the Kangax compatibility table for "Reserved words as property names"
http://kangax.github.io/compat-table/es5/#test-Object/array_literal_extensions_Reserved_words_as_property_names
I'm seeing code in the following form - is such use of eval() safe?
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset=eval("document."+frm_name);
var x=eval("document."+frm_name+".edit_key");
var y=eval("document."+frm_name+".cAction")
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
Its used as:
<a href="javaScript:;" onClick="genericTakeAction('frmSearch',
'<?php echo $rec_id;?>','<?php echo $pagenum?>','makeOpen')"
class='link6'>Make Open</a>
Whether it's right or wrong, it's needlessly complicated.
function genericTakeAction(frm_name,id,pagenum,action)
{
var rset = document[frm_name];
var x = rset.edit_key;
var y = rset.cAction;
if(x)
x.value=id;
if(y)
y.value=action;
page_list(pagenum);
}
This works because in JavaScript, you can access an object's properties in one of two ways: Either using dotted syntax and a literal identifier, e.g. x = obj.foo;, or using bracket syntax and a string identifier, e.g. x = obj["foo"];. (Note how foo was not in quotes in the first one, but was in quotes for the second; but both do exactly the same thing. Also note that since the property name is a string in the second case, you can use any expression that results in a string, so y = "f"; x = obj[y + "oo"]; also works.)
P.S. It's wrong
eval() is generally frowned upon because, as you are already aware, it is considered unsafe.
In the browser environment, however, it is less of an issue, because in fact, any user could eval() any code they wanted to, using tools like Firebug, etc.
There is still an issue, in that the eval() embedded in the code can be run without the user knowing that he was triggering an eval(), but it's still much less of an issue than in a server-side environment like PHP.
eval() is actually typically used as you've shown to run JSON code being returned from a server-side request. Newer browsers can import JSON more safely using a dedicated JSON parse() function, but older browsers do not have this function and are forced to use eval() for this. Most JSON libraries have eval() in their code somewhere for this reason, but will generally do some sanitisation of the input before running it through eval().
Even if it might look a little bit convoluted, as others have already mentioned, from a pure security perspective, you have to make sure that the 'frm_name' parameter of the genericTakeAction() function can never contain user-supplied data.
In your example, the 'frm_name' parameter contains the hard-coded literal 'frmSearch'. So it is ok as long as this genericTakeAction() function does not get called somewhere else with user-supplied data for the 'frm_name' parameter.
See http://en.wikipedia.org/wiki/Cross-site_scripting#Traditional_versus_DOM-based_vulnerabilities
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Lately I've been writing some JS code using jQuery and JavaScript as it is and I thought I will give JSLint a try. Let me say that the code contains various functions and jQuery usages and it works fine (without any errors ) in IE8 and latest Firefox.
The code also validatas as XHTML 1.0 Transitional (and Strict too but I mostly want it to be Transitional valid).
However, with JSLint it's like everything is wrong. While I have read about it being very strict, even if I turn on only "The Good Parts" it's still like 70+ errors in a typical HTML page.
It starts out with this (why in the world would I want to remove the type to make my documents XHTML invalid??)
Problem at line 5 character 67: type is unnecessary.
<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
and goes on with esoteric errors like
Problem at line 41 character 41: Use the array literal notation [].
var rows = new Array();
Problem at line 42 character 30: Too many var statements.
for (var i = 0; i < data.length; i++) {
Problem at line 42 character 55: Unexpected use of '++'.
for (var i = 0; i < data.length; i++) {
Problem at line 64 character 50: ['PrettyId'] is better written in dot notation.
var item = $("#item_" + data["PrettyId"]);
If anyone can provide me answers to these errors and especially, how to make JSLint be aware of jQuery and understand it, I will appreciate it.
If not, please explain whether you use it or not and whether you advice to use it or not.
UPDATE:
I'm going to wait one more day for more answers, if any, then I'll accept the answer with the most upvotes.
A thing to remember when using JSLint is that is built on the opinion about what one person thinks is the "Good Parts".
I think is a great tool but there are rules that I don't agree with.
About the type attribute, you can find more about the opinion of the author here he says that the attribute is "required and non necessary", but if you validate your documents you clearly need it.
With the use of the Array literal notation [] vs. the Array constructor, I agree, there are differences that can make the two syntaxes behave different, for example:
[5]; // one-element array
["5"]; // one-element array
new Array(5); // empty array but its length is initialized with 5
new Array("5"); // one-element array
So, for consistency an brevity the literal notation is better.
About the "Too many var statements", JavaScript has no block-scope, the scope is at function or global level, and all var statements are evaluated before the code execution -aka hoisting- and they are initialized with undefined, while the assignments are made at runtime.
For example:
var x = 0;
if (true) {
var x = 1; // useless var, x already declared
}
x; // 1
And the "hoisting" of variable declaration can be shown in this example:
var x = 5; // global
(function () {
alert(x); // alerts `undefined`, x declared but unassigned in this scope
alert(y); // ReferenceError, y is undeclared
var x = 10;
})();
As you can see x holds undefined because it is declared before the actual code execution, the var statements are hoisted to the top of their enclosing scope:
var x = 5; // global
(function () {
var x;
alert(x); // alerts `undefined`, x declared but unassigned
alert(y); // ReferenceError, y is undeclared
x = 10; // assignment is made
})();
So that rule wants to actually make the code to resemble what will happen, all the var statements at first place.
About the "Unexpected use of '++'", this is another rule that I don't quite like, the author thinks that "those contribute to bad code by encouraging excessive trickiness".
When I use them in some expression, I try to extract the operator usage to an alone statement, for example:
array[++id] = x;
To:
id+=1;
array[id] = x;
Which is more clearer, but anyway in the case of a for statement IMO it can't cause any confusion at all...
About the last one "['PrettyId'] is better written in dot notation.", JSLint expects the usage of the bracket notation to be "dynamic", it expects to see an expression there, not a String literal that contains a valid identifier name, the bracket notation should be used only when you want to access a property with a name that clashes with a reserved word e.g.:
data.function; // SyntaxError in ECMAScript 3 based implementations
data["function"]; // Ok
Or when a property contains characters that are not a valid identifier, e.g.:
data.foo-bar; // it access the property `foo` minus a `bar` variable
data["foo-bar"]; // Ok
data.foo bar; // SyntaxError, unexpected `bar` identifier
data["foo bar"]; // Ok
I use jslint on .js files and find a combination of options and fixes to make it happy. I find it improves my code quality. I would recommend running it, even if you only use it to isolate omitted 'var' declarations.
I avoid the script tag warning by not running against html files. I use jslint systematically on .js files, but not on html. I find it is just too burdensome to declare all the global identifiers that got defined in included scripts, but aren't visible to jslint.
Crockford's book 'Javascript: The Good Parts' explains many if not all of the jslint warnings, and some of them are based on perceived bug proneness. The 'new Array()' vs ' []' warning is based on Doug's aversion to the 'new' operator. Omitting 'new' for various constructors is commonly valid code, but not correct code, and using the alternative syntax avoids that risk.
The 'too many vars' error means just that, a large number of 'var' declarations in a given function: the Crockford endorsed style is to use one or very few 'var' declarations, all at the top of the function. You can declare multiple variables in one var statement, by separating them with commas.
The '++' caution is another bug proneness based warning; Using '+=1' means the same thing, and Doug believes it to be less error prone.
jslint is thus a mixed bag. Some features (locals vs globals) are invaluable, some (script types) are just annoying, and many are of dubious benefit but harmless.
jQuery itself passes jslint checks, as described here:
http://docs.jquery.com/JQuery_Core_Style_Guidelines#JSLint
There's an old joke about a programmer who smoked. A friend said, "You're a really smart guy, can't you read the warning on the pack that says cigarettes will kill you?" Came the reply: "I'm a programmer. We only pay attention to errors, not warnings."
Sometimes JSLint tells you things that are critical, sometimes it just nags. You can get lost trying to make it happy, but you might just be lost without it. Like any other tool, its input should be taken with a grain of salt. I prefer to think of it like the spell-checker or grammar-checker in MS Word. Sometimes it's right, sometimes it's wrong, and sometimes I just don't care what it tells me.
It hurts when you start using it on your old code.
But then it will save you a lot of time.JSLint can detect many problems that you would only see when refreshing your page or worse when your users do.Now it hurts me when I have to use an editor without JSLint
Another advantage is when you start compressing your javascript. If you pass the JSLint checks, you are almost certain to compress without problems.
That being said, jquery has 23 warning, most of them about regex, but is widely used without any problems.
JSLint is a Code Quality tool. It's not like W3C validator. Consider it something like a weekly code review at a company. Coding conventions vary and JSLint is just one of them. There may be points you don't agree with, but if you work in a team and you need to manage a larger codebase JSLint can be a life saver. Why? Because it warns you about things that are confusing or error prone.
The best way to use JSLint is this: read everything it says and if you're unsure about something correct it as suggested (as it seems to be the case here).
The reason is that JSLint is meant to avoid confusion and if you're using something that can lead to errors and you don't know why, then you better off with a clear alternative.
And if you want to know the reasoning behind the suggestions watch Douglas Crockford's videos on Javascript.
Finally, you can turn off filters that you find useless.
you should use it. The fact that it works in one browser doesn't mean it will work in all browsers; some are more lenient than others. for example, having a trailing comma in an array will break in IE but work in FF.
Be aware that sometimes you get a ton of errors, but you remove the first and a dozen go away, like compiling code.
you can do
var rows = [];
for the first error.
Here are the best answers I can give. Perhaps someone can fill in some blanks. It doesn't appear as though any of these relate to jQuery, though.
Also, see this document for some explanations.
Problem at line 5 character 67: type is unnecessary.
<script src="/Scripts/jquery-1.4.2.min.js" type="text/javascript"></script>
and goes on with esoteric errors like
I believe that for modern browsers, there's no need for text/javascript when linking to external js files.
Problem at line 41 character 41: Use the array literal notation [].
var rows = new Array();
It is recommended to not call the constructor when creating an Object or Array. I'm honestly not sure why. Anyone?
Problem at line 42 character 30: Too many var statements.
for (var i = 0; i < data.length; i++) {
I suppose you have the i variable declared elsewhere in the same scope. A javascript block does not create scope, so if you have another for loop (for example) that uses i, it is using the same variable. No need to declare it again.
Problem at line 42 character 55: Unexpected use of '++'.
for (var i = 0; i < data.length; i++) {
Not sure about this one, except that if I recall correctly, Crockford doesn't like the ++ and --.
Problem at line 64 character 50: ['PrettyId'] is better written in dot notation.
var item = $("#item_" + data["PrettyId"]);
I believe . notation is preferred because it is shorter and faster (in some browsers anyway). So data.PrettyID instead.
As far as I can tell, nothing here appears to be explicitly wrong. Mostly just best practice advice from JSLint creator's perspective.