Board = function()
{
var cells = [8];
/**
* Initializing every cell using numeric format.
* */
for (var i=0 ; i<8; i++){
cells[i] = [8];
for (var j=0 ; j<8; j++)
cells[i][j] = new Cell(new Position(i,j));
}
....
}
In Another code GameManager.js,
var duplicateBoard = Copy.deepCopy(board);
board.moveCell(1,2)
And for Deepcopying I am using,
Ref : http://jsperf.com/deep-copy-vs-json-stringify-json-parse
function deepCopy(o) {
var copy = o,k;
if (o && typeof o === 'object') {
copy = Object.prototype.toString.call(o) === '[object Array]' ? [] : {};
for (k in o) {
copy[k] = deepCopy(o[k]);
}
}
return copy;
}
My need :
I want cells (private member of constructor ) in Board to be deep-copied.
Problem :
But, When I debugged with firebug, I saw, deepCopy function does not deep copying private objects of constructor.
My Case :
board.moveCell(1,2), Here cell[1][2] is moved in duplicateBoard too.
That is,
No deep-copying of cell has taken place
Both the board and duplicateBoard has same reference to cell[1][2].
What I have traced ?
The deep-copy function, treats the constructor to be a function, hence it ignores deep-copying the functions, since it will fail in typeof o === 'object. But removing this condition is not useful, because by doing so, duplicateBoard has no functions rather all the functions to be object{} type.
This cannot be done as the "private" variable is local to the function(constructor). With the way that JS works, even by cloning the functions you will still get a pointer from the original object (http://jsfiddle.net/kBzQP/),
function deepCopy(o) {
if(o == null || typeof(o) != 'object') {
return o;
}
var newObj = new o.constructor();
for(var key in o) {
newObj[key] = deepCopy(o[key]);
}
return newObj;
}
if you do not clone functions then you get a brand new set of private variables with all the public variables cloned (http://jsfiddle.net/kBzQP/3/).
function deepCopy(o) {
if(o == null || typeof(o) != 'object') {
return o;
}
var newObj = new o.constructor();
for(var key in o) {
if(typeof(o) != 'function') continue;
newObj[key] = deepCopy(o[key]);
}
return newObj;
}
The best way to handle this is to make your private variables publicly accessible but give them a different naming convention such as "_myPrivateVariable". This way the variables will be cloned and anyone else using your class will know that this is a private variable.
So in your case it would be:
Board = function()
{
this._cells = [8];
/**
* Initializing every cell using numeric format.
* */
for (var i=0 ; i<8; i++){
this._cells[i] = [8];
for (var j=0 ; j<8; j++)
this._cells[i][j] = new Cell(new Position(i,j));
}
....
}
For reference sake check here: Copy javascript object with private member
It's not a good solution as all functions accessing your "private" cells variable have to declared as this.someFunction instead of Board.prototype so each Board instance will have their own funcions instead of sharing them.
Here is some sample code that would break prototype (c instanceof b is not true) but since you can't use prototype because you need to access closure variables in your functions that would not matter.
function Test(privates) {
var msg = [];
if(privates!==undefined){
msg=deepCopy(privates.msg,[]);
}
this.Message = function(newMsg) {
if (newMsg) {
msg.push(newMsg);
} else {
return msg;
}
}
this.clone=function(){
var orgMsg=msg
var ret = function(){
Test.call(this,{msg:orgMsg});
}
return deepCopy(this,new ret());
}
}
// this does not set prototype correctly
function deepCopy(from,to) {
if(from == null || typeof(from) != 'object') {
return from;
}
for(var key in from) {
// this.Message has closure ref to msg
// you can't copy it because we've set a new
// closure ref
if(typeof from[key]!=="function"){
to[key] = deepCopy(from[key]);
}
}
return to;
}
var b = new Test();
b.Message("Before cloning");
console.log("b message before cloning:",b.Message());
var c = b.clone();
console.log("c message after cloning:",c.Message());
b.Message("From BB after Clone");
console.log("c message after pushing new item in b:",c.Message());
c.Message("From CC after Clone");
console.log("b message after pushing new item in c:",b.Message());
console.log("c message after pushing new item in b:",c.Message());
[UPDATE]
Why this is a bad desing is because you can't declare your object methods as prototype:
Test.prototype.Message(){
//here the msg variable doesn't exist
}
This forces you to declare all your methods in the Test body with "this.someFunction" syntax. If you create multiple Test instances than each instance has it's own set of methods doing the exact same thing. To save resources you should use prototype but then you can't access closure varibales in these funcitons so you can't. Please read this on prototype basics: Prototypical inheritance - writing up
Maybe if you only have a couple of instances it wouldn't matter but technically you can't clone these objects. A real clone of b in the above code would be typeof Test but in the code above cloned instance of "b" called "c" is not typeof Test and there is no way I can see setting it without breaking the newly set closure variable called "msg".
Use $.extend():
var testObj = function() {
var rand = Math.random(0, 1);
this.r = function() {
return rand;
};
this.changeRand = function() {
rand = Math.random(0, 1);
};
};
var obj1 = new testObj();
alert(obj1.r());
obj1.changeRand();
alert(obj1.r());
var obj2 = $.extend(true, {}, obj1);
alert(obj2.r());
alert(obj1.r() === obj2.r()); // true
JSFiddle
In the same way you should use it for your board:
var Board = function() {
var cells = [8];
/**
* Initializing every cell using numeric format.
* */
for (var i=0 ; i<8; i++){
cells[i] = [8];
for (var j=0 ; j<8; j++)
cells[i][j] = new Cell(new Position(i,j));
}
}
var board = new Board(),
copy = $.extend(true, {}, board);
Normally I try to avoid using jQuery, but in this case it seems perfect...
Related
I am currently doing this by this method. Need a better implementation for this Scenario:
Here is the following:
var testjson = {
"key1":"val1",
"key2":"val2",
"key3":{
"k2":"v2",
"k3":{
"k4":"v4",
"k5":"v5"
}
},
"haskey": function (base, path) {
var current = base;
var components = path.split(".");
for (var i = 0; i < components.length; i++) {
if ((typeof current !== "object") || (!current.hasOwnProperty(components[i]))) {
return false;
}
current = current[components[i]];
}
return true;
}
}
console.log( testjson.haskey(testjson,"key3.k3.k4"));
First of all Sorry for asking misleading question.I just need a method for checking a nested object Property exists in a JavaScript object or not. There is nothing to do with prototype with this question. I just created a custom method with two argument one for object and another for property to check.This works fine, I came to a conclusion after looking at this ans->Checking if a key exists in a JavaScript object?
Here is my Method to check the property exist or not in an Object
var testobject = {
"key1": "value",
"key2": {
"key3": "value"
}
}
function checkproperty(object, path) {
var current = object;
var components = path.split(".");
for (var i = 0; i < components.length; i++) {
if ((typeof current !== "object") || (!current.hasOwnProperty(components[i]))) {
return false;
}
current = current[components[i]];
}
return true;
}
console.log(checkproperty(testobject, "key2.key3"))
Here I am in a situation where I have to work only with strings, and because of this I also have to retrieve the value of an object from strings, in short:
to retrieve the value from an object we write:
someObject.property1.name // for say
but in my case i want to retrieve value from an object using string, i.e
'someObject.property1.name' // for say
since I was not so confident that I could do this, so I preferred tho search on internet and the most suitable solution which I got was
#1
Object.byString = function(o, s) {
s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
var a = s.split('.');
while (a.length) {
var n = a.shift();
if (n in o) {
o = o[n];
} else {
return;
}
}
return o;
}
from here
#2
var deep_value = function(obj, path){
for (var i=0, path=path.split('.'), len=path.length; i<len; i++){
obj = obj[path[i]];
};
return obj;
};
from here
but as I said they are the most suitable example because they all are taking one extra parameter i.e. obj, O and so on... which is creating trouble for me, so I tried to improve the above code in search 2 because it is compact, and that results in failure. That code is:
var obj = {
foo: { bar: 'baz' }
};
var deep_value = function(path){
var obj = path.split('.');
obj = obj[0];
for (var i=0, path=path.split('.'), len=path.length; i<len; i++){
obj = obj[path[i+1]];
};
return obj;
};
alert(deep_value('obj.foo.bar'));
(I edited in his code for just an experiment). the above code does not need obj which is a perfect code - if it worked - and don't see any mistake, then why this code is not working, what is the correct code?
JSFIDDLE
thanks in advance
There were a couple problems with your #3 option:
First obj = obj[0]; was just going to have obj === "obj" which isn't going to help you at all. You need to actually get window["obj"] to get the top level object.
Second, you were traversing the for loop one too many times and going off the end of the path array.
Making changes in both these areas will make it work if obj is at the top level scope:
var obj = {
foo: { bar: 'baz' }
};
var deep_value = function(path, baseObj){
baseObj = baseObj || window;
var obj = path.split('.');
obj = baseObj[obj[0]];
for (var i=1, path=path.split('.'), len=path.length; i<len; i++){
obj = obj[path[i]];
};
return obj;
};
alert(deep_value('obj.foo.bar'));
Working demo: http://jsfiddle.net/jfriend00/jGb5p/
Here's a bit of a cleaned-up version:
var obj = {
foo: { bar: 'baz' }
};
var deep_value = function(path, baseObj){
baseObj = baseObj || window;
var pieces = path.split('.');
// get root level object
var obj = baseObj[pieces[0]];
for (var i = 1, len = pieces.length; i < len; i++){
obj = obj[pieces[i]];
}
return obj;
};
console.log(deep_value('obj.foo.bar'));
Working demo: http://jsfiddle.net/jfriend00/7J4Jb/
This be expressed compactly using reduce:
function eval_dotted_path(path) {
return path.split('.').reduce(function(value, segment) {
return value && value[segment];
}, window);
}
This splits up the path into "segments" on the dots, then calls reduce to "loop" over the segments, finding the next value inside the object on each iteration. The first segment is found in the global namespace, aka "window".
The value && value[segment] ensures that if at any point the current value is null/undefined (because the segment property was not present), undefined/null is returned.
If instead you want to find the value indicated by the dotted path starting from a known object, you can tweak this as
function eval_dotted_path_from_object(object, path) {
return path.split('.').reduce(function(value, segment) {
return value && value[segment];
}, object);
}
after which you can redefine the initial function as
function eval_dotted_path(path) {
return eval_dotted_path_from_object(window, path);
}
If you're in an old environment without Array.prototype.reduce, consider using Underscore's _.reduce, or a polyfill; some frameworks may provide the polyfill for you.
I have a JavaScript object created from JSON. I really need to set its prototype property to be a different object because of JS5 getters and setters. Here is an example of what I need that works on Chrome:
function MyObj() { }
MyObj.prototype = {
get myProp : function () { return this._myProp; },
set myProp : function (arg) { this._myProp = arg; }
}
... stuff ...
var instance = JSON.parse(result);
instance.constructor = MyObj;
instance.__proto__ = MyObj.prototype;
With this code, I can get and set properties on instance using the getters and setters defined in the prototype. However, this is not portable and will not work on IE, (nor node, I think).
What is the proper and portable way of doing this?
Think the other way around:
Create a new instance of MyObj and then copy the properties of instance to it. Or give MyObj a constructor that does that, when you provide it with an argument:
function MyObj(instance) {
if (instance) {
//copy properties
This way you may be even able to do
var instance = new MyObj(JSON.parse(result));
You could try using a JSON reviver function.
function revive(json) {
var m = new MyObj(), y;
return JSON.parse(json, function(k, v){
if (!y) y = this;
return k == "" ? m : this == y ? m[k] = v : v
});
}
Call revive('... a json string ...'), it will spit out an instance of MyObj with the properties defined in the JSON string.
Caveat: this will only work if the first item in your JSON object is a primitive value. If that's not possible in your case, here's a rather ugly workaround:
function revive(json) {
var m = new MyObj(), c = json.charAt(0), y, a;
if (c == '[') {
a = json = '[0,' + json.substring(1);
} else if (c == '{') {
json = '{"#":0,' + json.substring(1);
}
return JSON.parse(json, function(k, v){
if (!y) { y = this; return; }
return k == "" ? m : this == y ? m[a ? k - 1 : k] = v : v
});
}
Say i have this function that dynamically creates my namespace for me when I just pass it a string, (I'm pretty sure basically what YUI JS library does):
MyObj.namespace('fn.method.name');
would result in
MyObj.fn.method.name = {}
being created - all three levels being equivalent to an empty object.
Now, what I want to do, though, is make the last level, in this case name, set to a function, but without having to redeclare the newly created object.
So instead of doing this:
function fnName() { /* some code here */ }
MyObj.namespace('fn.method.name');
MyObj.fn.method.name = new fnName();
i want to call something like:
MyObj.add('fn.method.name', fnName);
And internally, the add method would programmatically instantiate the passed in function:
MyObj.fn.method.name = new fnName()
In the way I have it implemented, I can create the namespace object and set it to an empty object, however, when I try to instantiate a passed in function and associate that namespace with the passed in function, it never gets added to the namespace. Instead, an empty object is always returned. Any ideas?
edit: Here is the namespace method. this is attached to the base object as a JSON object, so please ignore the formatting:
namespace: function (ns) {
var _ns = ns.split('.'),
i = 0, nsLen = _ns.length,
root = this;
if (_ns[0] === gNS) {
_ns.shift();
nsLen = _ns.length;
}
for (i = 0; i < nsLen; i++) {
// create a property if it doesn't exist
var newNs = _ns[i];
if (typeof root[newNs] === "undefined") {
root[newNs] = {};
}
root = root[newNs];
}
return root;
}
edit2 - removed the passed in fn argument
Were you looking for something like this:
var root = {};
function create(ns, fn) {
var nsArray = ns.split(/\./);
var currentNode = root;
while(nsArray.length > 1) {
var newNS = nsArray.shift();
if(typeof currentNode[newNS] === "undefined") {
currentNode[newNS] = {};
}
currentNode = currentNode[newNS];
}
if(fn) {
currentNode[nsArray.shift()] = fn;
}
else {
currentNode[nsArray.shift()] = {};
}
}
Then:
create("a.b.c");
console.log(root.a);
console.log(root.a.b);
console.log(root.a.b.c);
Gives:
Object { b={...}}
Object { c={...}}
Object {}
And:
create("d.e.f", function() { console.log("o hai"); });
console.log(root.d);
console.log(root.d.e);
console.log(root.d.e.f);
Gives:
Object { e={...}}
Object {}
function()
Calling the function you defined:
root.d.e.f();
Gives:
o hai
Well you haven't given the namespace function but your add function could look something like this:
MyObj.add = function (namespace, value) {
var names = namespace.split('.'), current = this, name;
while (names.length > 1) {
name = names.shift();
current[name] = {};
current = current[name];
}
current[names[0]] = value;
};
This code assigns the value given to the last part of the namespace. You could modify it to current[names[0] = new value(); if you want the object constructed by the passed in function (and you are assuming the constructor function takes no arguments).
function ns() {
var root = window;
for (var i = 0; i < arguments.length; i++) {
var arr = arguments[i].split(/\./);
for (var j = 0; j < arr.length; j++) {
var item = arr[j];
if (typeof item !== 'string') {
root = item;
}
else {
if (!root[item]) {
root[item] = {};
}
root = root[item];
}
}
root = window;
}
}
then you can create using
ns('fn.method.name');
or
ns('fn.method.name','fn.method.secondName');
and call using
fn.method.name
this function creates your namespace on 'window' so alternatively you can use
window.fn.method.name
Do you know a JavaScript library that implements a generic Iterator class for collections (be it Arrays or some abstract Enumerable) with a full set of features, like the Google Common or the Apache Commons?
Edit: Enumerable#each is not an Iterator class. I'm looking for an Iterator, something that would let us write something like:
var iterator = new Iterator(myCollection);
for (var element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
// iterator
}
Edit : mamoo reminded us of the Iterator implementation in Mozilla's Javascript 1.7. So the goal now is to find an implementation of this Iterator function in Javascript 1.5 (ECMA 4).
Edit2 : Why using an iterator when libraries (and ECMA 5) provide a each method? First, because each usually messes with this because the callback is call -ed (that's why each accepts a second argument in Prototype). Then, because people are much more familiar with the for(;;) construct than with the .each(callback) construct (at least, in my field). Lastly, because an iterator can iterate over plain objects (see JavaScript 1.7).
Edit3 : I accepted npup's anwser, but here is my shot at it :
function Iterator(o, keysOnly) {
if (!(this instanceof arguments.callee))
return new arguments.callee(o, keysOnly);
var index = 0, keys = [];
if (!o || typeof o != "object") return;
if ('splice' in o && 'join' in o) {
while(keys.length < o.length) keys.push(keys.length);
} else {
for (p in o) if (o.hasOwnProperty(p)) keys.push(p);
}
this.next = function next() {
if (index < keys.length) {
var key = keys[index++];
return keysOnly ? key : [key, o[key]];
} else throw { name: "StopIteration" };
};
this.hasNext = function hasNext() {
return index < keys.length;
};
}
var lang = { name: 'JavaScript', birthYear: 1995 };
var it = Iterator(lang);
while (it.hasNext()) {
alert(it.next());
}
//alert(it.next()); // A StopIteration exception is thrown
var langs = ['JavaScript', 'Python', 'C++'];
var it = Iterator(langs);
while (it.hasNext()) {
alert(it.next());
}
//alert(it.next()); // A StopIteration exception is thrown
Ok, the enumerable pattern is not a real iterator then.
Is this (below) useful for you? It conforms to the sematics you gave at least. As usual there are tradeoffs to be made here and there, and I didn't think very hard when deciding this time :).
And maybe you would like to be able to send in a number or two and iterate over a range in that way. But this could maybe be a start (there's support for iterating over hashes, arrays and strings).
It's a whole demo page which runs itself and does some debug output, but the (possibly) interesting stuff is in the
window.npup = (function() {
[...]
})();
spot.
Maybe it is just me who doesn't get it at all, but what would you use such a java-like Iterator for in a real situation?
Best
/npup
<html>
<head>
<title>untitled</title>
</head>
<body>
<ul id="output"></ul>
<script type="text/javascript">
window.log = (function (outputAreaId) {
var myConsole = document.getElementById(outputAreaId);
function createElem(color) {
var elem = document.createElement('li');
elem.style.color = color;
return elem;
}
function appendElem(elem) {
myConsole.appendChild(elem);
}
function debug(msg) {
var elem = createElem('#888');
elem.innerHTML = msg;
appendElem(elem);
}
function error(msg) {
var elem = createElem('#f88');
elem.innerHTML = msg;
appendElem(elem);
}
return {
debug: debug
, error: error
};
})('output');
window.npup = (function () {
// Array check as proposed by Mr. Crockford
function isArray(candidate) {
return candidate &&
typeof candidate==='object' &&
typeof candidate.length === 'number' &&
typeof candidate.splice === 'function' &&
!(candidate.propertyIsEnumerable('length'));
}
function dontIterate(collection) {
// put some checks chere for stuff that isn't iterable (yet)
return (!collection || typeof collection==='number' || typeof collection==='boolean');
}
function Iterator(collection) {
if (typeof collection==='string') {collection = collection.split('');}
if (dontIterate(collection)) {throw new Error('Oh you nasty man, I won\'t iterate over that ('+collection+')!');}
var arr = isArray(collection);
var idx = 0, top=0;
var keys = [], prop;
if (arr) {top = collection.length;}
else {for (prop in collection) {keys.push(prop);}}
this.next = function () {
if (!this.hasNext()) {throw new Error('Oh you nasty man. I have no more elements.');}
var elem = arr ? collection[idx] : {key:keys[idx], value:collection[keys[idx]]};
++idx;
return elem;
};
this.hasNext = function () {return arr ? idx<=top : idx<=keys.length;};
}
return {Iterator: Iterator};
})();
var element;
log.debug('--- Hash demo');
var o = {foo:1, bar:2, baz:3, bork:4, hepp: {a:1,b:2,c:3}, bluff:666, bluff2:777};
var iterator = new npup.Iterator(o);
for (element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
log.debug('got elem from hash: '+element.key+' => '+element.value);
if (typeof element.value==='object') {
var i2 = new npup.Iterator(element.value);
for (var e2=i2.next(); i2.hasNext(); e2=i2.next()) {
log.debug(' # from inner hash: '+e2.key+' => '+e2.value);
}
}
}
log.debug('--- Array demo');
var a = [1,2,3,42,666,777];
iterator = new npup.Iterator(a);
for (element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
log.debug('got elem from array: '+ element);
}
log.debug('--- String demo');
var s = 'First the pants, THEN the shoes!';
iterator = new npup.Iterator(s);
for (element = iterator.next(); iterator.hasNext(); element = iterator.next()) {
log.debug('got elem from string: '+ element);
}
log.debug('--- Emptiness demo');
try {
log.debug('Try to get next..');
var boogie = iterator.next();
}
catch(e) {
log.error('OW: '+e);
}
log.debug('--- Non iterables demo');
try{iterator = new npup.Iterator(true);} catch(e) {log.error('iterate over boolean: '+e);}
try{iterator = new npup.Iterator(6);} catch(e) {log.error('iterate over number: '+e);}
try{iterator = new npup.Iterator(null);} catch(e) {log.error('iterate over null: '+e);}
try{iterator = new npup.Iterator();} catch(e) {log.error('iterate over undefined: '+e);}
</script>
</body>
</html>
JQuery has the each() method:
http://api.jquery.com/jQuery.each/
but probably there's something similar even in other libraries such as Moo or Dojo.
Javascript 1.7 implements the Iterator function:
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Iterators_and_Generators
This is my attempt (jsfiddle) for ECMAScript 262 5th edition (aka Javascript). (Uses for example Object.keys and Array.isArray)
//Usage
b=Iterator(a);
while(b()){
console.log(b.value);
}
The code:
function Iterator(input,keys) {
// Input:
// input : object|array
// keys : array|undefined|boolean
function my() {
++my.index;
if (my.index >= my.keys.length) {
my.index = my.keys.length -1;
my.key = my.value = undefined;
return false;
}
my.key = my.useIndex ? my.index : my.keys[my.index];
my.value = my.input[my.key];
return my.index < my.keys.length;
}
if (input === null || typeof input !== 'object') {
throw new TypeError("'input' should be object|array");
}
if (
!Array.isArray(keys)
&& (typeof keys !== 'undefined')
&& (typeof keys !== 'boolean')
) {
throw new TypeError("'keys' should be array|boolean|undefined");
}
// Save a reference to the input object.
my.input = input;
if (Array.isArray(input)) {
//If the input is an array, set 'useIndex' to true if
//the internal index should be used as a key.
my.useIndex = !keys;
//Either create and use a list of own properties,
// or use the supplied keys
// or at last resort use the input (since useIndex is true in that
// case it is only used for the length)
my.keys = keys===true ? Object.keys(input) : keys || input;
} else {
my.useIndex = false;
my.keys = Array.isArray(keys) ? keys : Object.keys(input);
}
// Set index to before the first element.
my.index = -1;
return my;
}
Examples:
function Person(firstname, lastname, domain) {
this.firstname = firstname;
this.lastname = lastname;
this.domain = domain;
}
Person.prototype.type = 'Brillant';
var list = [
new Person('Paula','Bean','some.domain.name'),
new Person('John','Doe','another.domain.name'),
new Person('Johanna','Doe','yet.another.domain.name'),
];
var a,b;
var data_array = ['A','B','C','D','E','F'];
data_array[10]="Sparse";
console.log('Iterate over own keys in an object, unknown order');
a = Iterator(list[0]);
while(a()) console.log(" ",a.key, a.value);
console.log('Iterate over keys from anywhere, in specified order');
a = Iterator(list[0], ['lastname','firstname','type']);
while(a()) console.log(" ",a.key, a.value);
console.log('Iterate over all values in an array');
a = Iterator(list);
while(a()) console.log(a.key, a.value.firstname, a.value.lastname);
//Some abusing, that works for arrays (if the iterator.keys is modified
//it can also be used for objects)
console.log('Add more entries to the array, reusing the iterator...');
list.push(new Person('Another','Name','m.nu'));
while(a()) console.log(a.key, a.value.firstname, a.value.lastname);
console.log('Reset index and print everything again...');
a.index=-1; //Reset the index.
while(a()) console.log(a.key, a.value.firstname, a.value.lastname);
//With arrays, if setting 'keys' to true it will only print the
//elements that has values (If the array has more own enumerable values
//they too will be included)
console.log('Print sparce arrays...');
a = Iterator(data_array,true);
while(a()) console.log(a.key, a.value);
In the time since this question was asked JavaScript has added actual Iterators. Some built-in types, such as Array, Map, and String now have a default iteration behavior, but you can add your own to any object by including a next() function which returns one of two objects:
{done:true} /*or*/
{done:false, value:SOMEVALUE}
One way to access an object Iterator is with the:
for ( var of object ) { }
loop. Here is a (reasonably silly) example where we define an Iterator and then use it in such a loop to produce a string 1, 2, 3:
"use strict";
function count ( i ) {
let n = 0;
let I = {};
I[Symbol.iterator] = function() {
return { next: function() { return (n > i) ? {done:true}
: {done:false, value:n++} } } };
let s = "";
let c = "";
for ( let i of I ) { /* use the iterator we defined above */
s += c + i;
c = ", "
}
return s;
}
let s = count(3);
console.log(s);
Ive used LINQ to Javascript in a few projects.
http://jslinq.codeplex.com/Wikipage
var myList = [
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Kate",LastName:"Johnson"},
{FirstName:"Josh",LastName:"Sutherland"},
{FirstName:"John",LastName:"Ronald"},
{FirstName:"Steve",LastName:"Pinkerton"}
];
var exampleArray = JSLINQ(myList)
.Where(function(item){ return item.FirstName == "Chris"; })
.OrderBy(function(item) { return item.FirstName; })
.Select(function(item){ return item.FirstName; });
I'm still a learner of js.class.
Though being close to Ruby, helps me.
http://jsclass.jcoglan.com/enumerable.html
MarkT
Since this hasn't been mention yet arrays have higher-order functions built in.
Map works like iterator that can only do a single pass.
[1,2,3,4,5].map( function(input){ console.log(input); } );
This code passes each element in the list into a function, in this case its a simple printer.
1
2
3
4
5