JavaScript array
!No description available for array. @php.js developers: Please update the function summary text file.
1 2 3 4 56 7 8 9 1011 12 13 14 1516 17 18 19 2021 22 23 24 2526 27 28 29 3031 32 33 34 3536 37 38 39 4041 42 43 44 4546 47 48 49 5051 52 53 54 5556 57 58 59 6061 62 63 64 6566 67 68 69 7071 72 73 74 7576 77 78 79 8081 82 83 84 8586 87 88 89 9091 92 93 94 9596 97 98 99 100101 102 103 104 105106 107 108 109 110111 112 113 114 115116 117 118 119 120121 122 123 124 125126 127 128 129 130131 132 133 134 135136 137 138 139 140141 142 143 144 145146 147 148 149 150151 152 153 154 155156 157 158 159 160161 162 163 164 165166 167 168 169 170171 172 173 174 175176 177 178 179 180181 182 183 184 185186 187 188 189 190191 192 193 194 | function array () { // !No description available for array. @php.js developers: Please update the function summary text file. // // version: 1109.2015 // discuss at: http://phpjs.org/functions/array // + original by: d3x // + improved by: Brett Zamir (http://brett-zamir.me) // * example 1: array('Kevin', 'van', 'Zonneveld'); // * returns 1: ['Kevin', 'van', 'Zonneveld'] // * example 2: ini_set('phpjs.return_phpjs_arrays', 'on'); // * example 2: var arr = array({0:2}, {a:41}, {2:3}).change_key_case('CASE_UPPER').keys(); // * returns 1: [0,'A',2] var mainArgs = arguments, p = this.php_js = this.php_js || {}, _indexOf = function (value, from, strict) { for (var i = (from || 0), nonstrict = !strict, length=this.length; i < length; i++) { if (this[i] === value || (nonstrict && this[i] == value)) { return i; } } return -1; }; // BEGIN REDUNDANT if (!p.Relator) { p.Relator = function () {// Used this functional class for giving privacy to the class we are creating // Code adapted from http://www.devpro.it/code/192.html // Relator explained at http://webreflection.blogspot.com/2008/07/javascript-relator-object-aka.html // Its use as privacy technique described at http://webreflection.blogspot.com/2008/10/new-relator-object-plus-unshared.html // 1) At top of closure, put: var __ = Relator.$(); // 2) In constructor, put: var _ = __.constructor(this); // 3) At top of each prototype method, put: var _ = __.method(this); // 4) Use like: _.privateVar = 5; function _indexOf (value) { for (var i = 0, length=this.length; i < length; i++) { if (this[i] === value) { return i; } } return -1; } function Relator () { var Stack = [], Array = []; if (!Stack.indexOf) { Stack.indexOf = _indexOf; } return { // create a new relator $ : function () { return Relator(); }, constructor : function (that) { var i = Stack.indexOf(that); ~i ? Array[i] : Array[Stack.push(that) - 1] = {}; this.method(that).that = that; return this.method(that); }, method : function (that) { return Array[Stack.indexOf(that)]; } }; } return Relator(); }(); } // END REDUNDANT if (p && p.ini && p.ini['phpjs.return_phpjs_arrays'].local_value.toLowerCase() === 'on') { if (!p.PHPJS_Array) { // We keep this Relator outside the class in case adding prototype methods below // Prototype methods added elsewhere can also use this ArrayRelator to share these "pseudo-global mostly-private" variables var __ = p.ArrayRelator = p.ArrayRelator || p.Relator.$(); // We could instead allow arguments of {key:XX, value:YY} but even more cumbersome to write p.PHPJS_Array = function PHPJS_Array () { var _ = __.constructor(this), args = arguments; args = (args.length === 1 && args[0] && typeof args[0] === 'object' && args[0].length && !args[0].propertyIsEnumerable('length')) ? args[0] : args; // If first and only arg is an array, use that (Don't depend on this) if (!_.objectChain) { _.objectChain = args; _.object = {}; _.keys = []; _.values = []; } for (var i=0, argl = args.length; i < argl; i++) { for (var p in args[i]) { // Allow for access by key; use of private members to store sequence allows these to be iterated via for...in (but for read-only use, with hasOwnProperty or function filtering to avoid prototype methods, and per ES, potentially out of order) this[p] = _.object[p] = args[i][p]; // Allow for easier access by prototype methods _.keys[_.keys.length] = p; _.values[_.values.length] = args[i][p]; break; } } }; var e = p.PHPJS_Array.prototype, that = this; e.change_key_case = function (cs) {var _ = __.method(this); var case_fn = (!cs || cs === 'CASE_LOWER') ? 'toLowerCase' : 'toUpperCase'; for (var i=0, kl = _.keys.length; i < kl; i++) { var oldkey = _.keys[i], newkey = _.keys[i] = _.keys[i][case_fn](); this[newkey] = _.object[newkey] = _.objectChain[i][newkey] = _.values[i]; // Fix: should we make a deep copy? this[oldkey] = _.object[oldkey] = _.objectChain[i][oldkey] = null; // Break reference before deleting delete this[oldkey]; delete _.object[oldkey]; delete _.objectChain[i][oldkey]; } return this; }; // Here we'll return actual arrays since most logical and practical for these functions to do this e.keys = function (search_value, argStrict) {var _ = __.method(this); var pos, search = typeof search_value !== 'undefined', tmp_arr = [], strict = !!argStrict; if (!search) { return _.keys; } while ((pos = _indexOf(_.values, pos, strict)) !== -1) { tmp_arr[tmp_arr.length] = _.keys[pos]; } return tmp_arr; }; e.values = function () {var _ = __.method(this); return _.values; }; // Return non-object, non-array values, since most sensible e.search = function (needle, argStrict) {var _ = __.method(this); var strict = !!argStrict, haystack = _.values, i, vl, val; if (typeof needle === 'object' && needle.exec) { // Duck-type for RegExp if (!strict) { // Let's consider case sensitive searches as strict var flags = 'i' + (needle.global ? 'g' : '') + (needle.multiline ? 'm' : '') + (needle.sticky ? 'y' : ''); // sticky is FF only needle = new RegExp(needle.source, flags); } for (i=0, vl = haystack.length; i < vl; i++) { val = haystack[i]; if (needle.test(val)) { return _.keys[i]; } } return false; } for (i=0, vl = haystack.length; i < vl; i++) { val = haystack[i]; if ((strict && val === needle) || (!strict && val == needle)) { return _.keys[i]; } } return false; }; // Experimental functions e.foreach = function (handler) {var _ = __.method(this); for (var i = 0, kl = _.keys.length; i < kl; i++) { if (handler.length === 1) { handler(_.values[i]); // only pass the value } else { handler(_.keys[i], _.values[i]); } } return this; }; e.list = function () {var _ = __.method(this); for (var i = 0, argl = arguments.length; i < argl; i++) { var key = _.keys[i]; if (key && key.length === parseInt(key).toString().length && // Key represents an int parseInt(key) < argl) { // Key does not exceed arguments that.window[arguments[key]] = _.values[key]; } } return this; }; // Parallel functionality and naming of built-in JavaScript array methods e.forEach = function (handler) {var _ = __.method(this); for (var i = 0, kl = _.keys.length; i < kl; i++) { handler(_.values[i], _.keys[i], this); } return this; }; // Our own custom convenience functions e.$object = function () {var _ = __.method(this); return _.object; }; e.$objectChain = function () {var _ = __.method(this); return _.objectChain; }; } function PHPJS_Array() {} PHPJS_Array.prototype = p.PHPJS_Array.prototype; var arrInst = new PHPJS_Array(); p.PHPJS_Array.apply(arrInst, mainArgs); return arrInst; } return Array.prototype.slice.call(mainArgs); } |
Examples
» Example 1
Running
1 | array('Kevin', 'van', 'Zonneveld'); |
Should return
1 | [0,'A',2] |
» Example 2
Running
1 2 | ini_set('phpjs.return_phpjs_arrays', 'on'); var arr = array({0:2}, {a:41}, {2:3}).change_key_case('CASE_UPPER').keys(); |
Should return
1 |
Dependencies
No dependencies, you can use this function standalone.
Open syntax issues
php.js uses JsLint to help us keep our code consistent and prevent some common bugs.
Eventually we want all code to pass or at least take into consideration most fixes suggested by JsLint, following this JsLint configuration we’ve decided on.
Authors
Thanks to the following developers, you get to have array goodness in JavaScript.
@ Ates Goral: Wow thanks a lot Ates! We'll leave it open for improvement then! Though I don't really like the idea of global variables, I believe the include_once functions also already work like that so we may be able to do that here as well. What do you think?
Perhaps the each() implementation I have below is a hasty one. It won't play nice with reset(), next() and previous(). It can be improved by actually storing the cursor position instead of consuming the key array with the shift(). I'll try to improve it and provide reset/next/prev if I find the time.
I apologize for the earlier, unformatted post :)
[CODE="Javascript"]
function each(arr) {
// Return the current key and value pair from an array and advance the array cursor
// + original by: Ates Goral (http://magnetiq.com)
// * example 1: each([42,43]);
// * returns 1: {0: 0, 1: 42, key: 0, value: 42}
// * example 2: each({a:"apple",b:"balloon"});
// * returns 2: {0:"a",1:"apple",key:"a",value:"apple"}
if (!(arr instanceof Object) || (arr._keys && !arr._keys.length)) {
return false;
}
if (!arr._keys) {
arr._keys = [];
for (var k in arr) {
if (k != "_keys") {
arr._keys.push(k);
}
}
}
var k = arr._keys.shift();
var v = arr[k];
return {
0: k,
1: v,
key: k,
value: v
};
}
[/CODE]
function each(arr) {
// Return the current key and value pair from an array and advance the array cursor
// + original by: Ates Goral (http://magnetiq.com)
// * example 1: each([42,43]);
// * returns 1: {0: 0, 1: 42, key: 0, value: 42}
// * example 2: each({a:"apple",b:"balloon"});
// * returns 2: {0:"a",1:"apple",key:"a",value:"apple"}
if (!(arr instanceof Object) || (arr._keys && !arr._keys.length)) {
return false;
}
if (!arr._keys) {
arr._keys = [];
for (var k in arr) {
if (k != "_keys") {
arr._keys.push(k);
}
}
}
var k = arr._keys.shift();
var v = arr[k];
return {
0: k,
1: v,
key: k,
value: v
};
}
@ Sean & Onno Marsman: I totally agree with Onno. If we can't get it right, and people have to learn a different notation anyway, let's just stick with JavaScript.
@Sean: We already can create associative arrays with JS:
[CODE="Javascript"]
{
'first': 'kevin',
'last': 'Zonnevelt' //I don't know why this is with a T ;)
}
[/CODE]
Technically this is not an array but an object, but your proposal wouldn't return anything different. So we already have a syntax that is "not quite the same as php" and it does exactly the same.
Also think of using variables:
[CODE="Javascript"]
{ a: b, c: d}
[/CODE]
Your alternative would result in something like this, because proper escaping is needed:
[CODE="Javascript"]
array(" '"+addslashes(a)+"' => '"+addslashes(b)+"' ", " '"+addslashes(c)+"' => '"+addslashes(d)+"' " );
[/CODE]
I hope I didn't make any typo's, but I think my point is clear.
@Kevin: Could you not do:
[CODE="Javascript"]
array(" 'first' => 'kevin' ", " 'last' => 'Zonnevelt' " );
[/CODE]
It's not quite the same as php, but at least this way you could create hash arrays
@ thinsoldier: Yes that would be very nice, but I don't see how we could implement that unfortunately :( Here we run against the hard wall of language differences.


سياحة وسفر
Apr 17th