Does Javascript supports Sets? - javascript

Does Javascript supports Sets(list with unique objects only) ?
I have found this link, but from what I remember foreach in JS in not supported by every browser.

Are your keys strings?
Every JavaScript object is a map, which means that it can represent a set.
As illustrated in the page you mentioned, each object will accept only one copy of each key (attribute name). The value for the key/attribute doesn't matter.

jshashtable would allow you to store any object as a key, and use the same pattern as in the link you gave. In addition it supplies a method to get an array of keys, which you can then iterate over. It also has good cross-browser support, so should fit nicely into any environment.

Now with ES6 (and polyfills/shims like corejs) you have them:
Set - JavaScript | MDN
Example:
var mySet = new Set([1, 2, 3, 2, 1]); // => [1, 2, 3]
console.log(mySet.size);
console.log(mySet.has(3));
mySet.forEach(function(x){console.log(x)});
The Polifill is required since it is not supported by older browsers, so you can ignore it if you are aiming only at the latest ones.

You probably remember the Array.forEach() that is indeed not supported by older Opera and all IE browsers - the for (var x in ...) is part of the "native" JS as far as I know and is supported by all browsers.

JavaScript do support Set. Here is the link to canIuse website. It is supported by Chrome, Edge, Safari, Firefox, Opera and even IE. To declare set you can use Set() constructor.
let set = new Set();
set.add("John);
In this way you can use sets.

Related

Object.defineProperty for all browsers?

Asking about Object.defineProperty as demonstrated below:
function testComponent(){
var testProperty;
Object.defineProperty(this, "testProperty",
{
get : function()
{
return testProperty;
},
set : function(val)
{
testProperty = val;
}
});
}
Where it would be used like so:
testObject = new testComponent();
testObject.testProperty = "testValue";
Based on what I've seen so far, it looks like there is no cross browser solution, as I've tried using es5-shim with no luck, but I would like to confirm. I also found a reference to this post and my tests still fail in IE 7 & 8, can anyone shed any light on this?
I remember looking through a related question a few months ago somewhere on S/O and I think I saw someone had written a solution for this in an answer. Any general workarounds for getter / setters would also be appreciated. The idea is that I need some equivalent of a getter setter on an object without passing the parameter change through a method. I don't need IE6, but I would like to support browsers in the range of IE7+ ff 3.6+ , etc
QUnit tests below: (jsFiddles)
(these pass in all browsers on my machine except IE 7 & 8
direct use of defineProperty, no shims: http://jsfiddle.net/uSYFE/
fiddle using the ES5 shim, I'm assuming all I need to do is include it? : http://jsfiddle.net/hyperthalamus/ntwDy/
fiddle using the IE recommended solution : http://jsfiddle.net/hyperthalamus/xfvz3/
According to ES5-shim:
/!\ Object.defineProperty
This method will silently fail to set "writable", "enumerable", and "configurable" properties.
Providing a getter or setter with "get" or "set" on a descriptor will silently fail on engines that lack "defineGetter" and "defineSetter", which include all versions of IE up to version 8 so far.
IE 8 provides a version of this method but it only works on DOM objects. Thus, the shim will not get installed and attempts to set "value" properties will fail silently on non-DOM objects.
https://github.com/kriskowal/es5-shim/issues#issue/5
So you know your answer. It can be done on DOM elements, that's it (and on IE8 only).
I'd suggest you just use get/set methods if you want IE7 to work.
For older IEs you'd have to make sure your property is a dom object (even a fake tag) and use onPropertyChange to get notified. See this post by John Dyer for more details.
I've had this same question myself. (See here.) It doesn't look like it's fully possible in IE8 or lower. Otherwise the ES5 Shim is your best bet.

Does Javascript have an enhanced for loop syntax similar to Java's

I am wondering if JavaScript has an enhanced for loop syntax that allows you to iterate over arrays. For example, in Java, you can simply do the following:
String[] array = "hello there my friend".split(" ");
for (String s : array){
System.out.println(s);
}
output is:
hello
there
my
friend
Is there a way to do this in JavaScript? Or do I have to use array.length and use standard for loop syntax as below?
var array = "hello there my friend".split(" ");
for (i=0;i<array.length;i++){
document.write(array[i]);
}
JavaScript has a foreach-style loop (for (x in a)), but it is extremely bad coding practice to use it on an Array. Basically, the array.length approach is correct. There is also a a.forEach(fn) method in newer JavaScripts you can use, but it is not guaranteed to be present in all browsers - and it's slower than the array.length way.
EDIT 2017: "We'll see how it goes", indeed. In most engines now, .forEach() is now as fast or faster than for(;;), as long as the function is inline, i.e. arr.forEach(function() { ... }) is fast, foo = function() { ... }; arr.forEach(foo) might not be. One might think that the two should be identical, but the first is easier for the compiler to optimise than the second.
Belated EDIT 2020: There is now for (const item of iterable), which solves the downsides of using for (item in iterable).
Using the latest versions of JavaScript available to most modern browsers, you can do this:
array.forEach(function(x){
document.write(x);
});
Details are at https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach. If you're worried that a browser may not have support for this, you can add it yourself, using a (hopefully minified) version of the implementation that they have listed under "Compatibility".
This is a bit outdated, but this is a minified compatibility version of forEach that I derived from Mozilla's page a few years ago:
if(!Array.prototype.forEach){Array.prototype.forEach=function(b){if(typeof b!="function"){throw new TypeError()}var a=this.length,d=arguments[1],c;for(c=0;c<a;c++){if(c in this){b.call(d,this[c],c,this)}}}};
I've never run into any issues with this, but the implementation on Mozilla's page has since been expanded with some additional checks and code to make it compatible with ECMA-262, Edition 5, 15.4.4.18.
I have a file called common.js that I use and include on all of my pages to include this, as well as all of the other "Array extras" that were introduced with JavaScript 1.6, as listed at https://developer.mozilla.org/en/JavaScript/New_in_JavaScript/1.6#Array_extras. (I've been meaning to get this updated and published for public use.)
This may not be the fastest approach (see http://jsperf.com/for-vs-foreach/15 for some specifics - thanks for the link, Amadan) - but there is something to be said for conciseness and maintainability, etc. Additionally, it'll be very interesting to see how much of this disparity is optimized away by further JavaScript engine improvements over the next few months and years. :-)
In ES2015(ES6), you can use the for-of loop. It's supported in most browser with the exception of IE.
let array = [10, 20, 30];
for (let value of array) {
console.log(value);
}
See the Mozilla explanation here
You can do for(s in array), but be careful, it's not the same as a foreach.
In this case s is the key (index), not the value. You also need to use hasOwnProperty because in loops though the object's prototype also.
for(s in array){
if(array.hasOwnProperty(s)){
console.log(array[s]);
}
}
EDIT: As #Amadan pointed out, hasOwnProperty does iterate properties when they're added like this: array.test = function(){}. I suggest not using for...in.
EDIT2: If your using a modern web browser (anything that isn't IE < 9), you can use Array.forEach). #ziesemer points out that Mozilla has a shim for this if you need to support IE < 9.
array.forEach(function(s){
console.log(s);
});
NOTE: Personally I use jQuery for my JavaScript projects, and I use $.each.
$.each(array, function(i,s){
console.log(s);
});
There's the "forEach" method on the Array prototype in newer JavaScript engines. Some libraries extend the prototype themselves with a similar method.
Try this:
var errorList = new Array();
errorList.push("e1");
errorList.push("e2");
for (var indx in errorList) {
alert(errorList[indx]);
}
x = [1,2,3];
for (i in x) {
console.log(i);
}

How to remove particular element from an array

I have an array like treeids = ['a','b','c','d'];
I want to remove the 'b' element. By Using index we can do, but i want this with out using index, because those values comes dynamically into this array.
Just remove with the name only.
It should support in IE7 browser.
How to do this.
Thanks
JavaScript 1.6 provides Array.filter, which would suit your needs spot on.
Of course, as you can see from the Browser support table at the bottom, if you must support IE older then IE 9, you're out of luck.
jQuery provides jQuery.grep which does the same thing, but introduces the overhead of a separate library.
Underscore.js has _.filter, but again, this would be using a separate library for only one purpose.
try the following:
treeids.splice(treeids.indexOf('b'), 1);
Now treeids will contain the remaining...Here 'b' was the element to be removed. The argument of indexOf can come from a variable. Additionally you should check for error: the index shouldn't be -1.
This removes all the 'b's:
Array.prototype.remove= function(item){
var L= this.length, indexed;
while(L){
indexed= this[--L];
if(indexed=== itm) this.splice(L, 1);
}
return this;
}
splice is available in IE7 (and 6). It removes the number of items passed in the second argument, starting at the index specified by the first.

Firefox Javascript: Why does .all not work?

In IE, I can go like:
var x = document.getElementById("header");
alert(x.all[0].tagName);
If I try that in Firefox, I get the error "all is undefined".
What is the Firefox equivalent of IE's .all property?
.all is a Microsoft-specific extension to the DOM, and is not supported by any other browsers (except Opera, I believe, who simulate it in order to improve compatibility with sites written for IE).
You can use things like x.children and x.childNodes, or x.getElementById() and x.getElementsByTagName() to reference elements below the current one in the tree, depending on your usage. I suspect in this case x.children is what you're after.
all would be the name of an array. It is not a native javascript keyword.
You may want to look at childNodes instead.

Possible to assign to multiple variables from an array?

Is it a standard way to assign to multiple variables from an array in JavaScript?
In Firefox and Opera, you can do:
var [key, value] = "key:value".split(":");
alert(key + "=" + value); // will alert "key = value";
But it doesn't work in IE8 or Google Chrome.
Does anyone know a nice way to do this in other browsers without a tmp variable?
var tmp = "key:value".split(":");
var key=tmp[0], value=tmp[1];
Is this something that will come in an upcoming JavaScript version, or just custom implementation in FF and Opera?
Destructuring assignment was standardized in ECMAScript 2015 (a.k.a. ES6). But not all browsers have implemented destructuring yet (as of March 2016), and even when they do it will take a while before users update to a browser with support. See examples in the spec for all the awesome things you can do. Here are some:
// Assign from array elements
var [key, value] = "key:value".split(":");
// key => 'key'
// value => 'value'
// Assign from object properties
var {name: a, age: b} = {name: 'Peter', age: 5};
// a => 'Peter'
// b => 5
// Swap
[a, b] = [b, a]
// a => 5
// b => 'Peter'
Because this feature breaks backwards compatibility, you'll need to transpile the code to make it work in all browsers. Many of the existing transpilers support destructuring. Babel is a very popular transpiler. See Kangax´s table of browser and transpiler ES6-support.
More info:
Compatibility table for ES6 browser support
Exploring ES6 - Destructuring chapter
If you want to know what's coming, read the section on Destructuring Assignment.
https://developer.mozilla.org/en/New_in_javascript_1.7
What language features you can use is always dependent on your environment.
Developing for Mobile Safari (or a web stack for other browsers like the Palm Pre, Android, etc.) or AIR, for example, is more predictable than developing for the web at large (where you still have to take even IE6 into account).
A cross-browser solution to the problem at hand would be to initialize an array that had a list of the variables you want to fill in window.variable format, then just loop through. Can't imagine why you'd do it though. Seems like there would always be a better solution.
Use destructuring assignment, a feature of ES6:
var [x, y] = [1, 2];
console.log(x, y); // 1 2
I just had exactly same question, and as an exercise for myself came up with the following:
var key, value;
(function(arr){
key=arr[0];
value=arr[1];
})("key:value".split(":"));
alert(key + "=" + value);
Looks ugly to me, I'd rather use temp var (technically, I'm using here a temp variable anyway).
Edit: chrome supports that now. As for IE8: do we still care about it?
I don't think this is possible in a cross browser way. The best that I know which might help in a few circumstances is this:
// we'll pretend you don't need the key.
var value = "key:value".split(":")[1];
I think it should be a part of the new spec., then again it's a long read... :p
key = "key:value".split(":")[0];
value = "key:value".split(":")[1];
Only alternative I can think off.
I don't know how you are using this, but if I was able to determine my own format for the "key:value" string, I'd be tempted to use json to just eval the string into the necessary object:
var obj = eval("{'key':'key_str', 'value':'val_str'}");
alert(obj.key + "=" + ojb.value); //alerts "key_str=value_str

Categories

Resources