javascript数组降维

网上有不少提供数组降维的方法,但是一般是二维数组,并且对多维数组的处理不好。降维自然会想到用concat方法,如果只是全部循环用push的话,那样写起来更麻烦,必要时该用concat的就用concat。

function dist(arr) {
        var res = [];
        for (var i = 0; i < arr.length; i++) {
            if (Object.prototype.toString.call(arr[i]) === '[object Array]') {
                res = res.concat(dist(arr[i]));
            } else {
                res.push(arr[i]);
            }
        }
        return res;
    }
var re = dist([1, 2, [3, 4, [5, 6, [7, 8]]]]);
    console.log('re', re); //输出[1,2,3,4,5,6,7,8]

Javascript原生函数作为构造函数

关于数组(array)、对象(object)、函数(function)和正则表达式,我们通常喜欢以常量的形式来创建它们。实际上,使用常量和使用构造函数的效果是一样的(创建的值都是通过封装对象来包装)。
如前所述,应该尽量避免使用构造函数,除非十分必要,因为它们经常会产生意想不到的结果。
3.4.1 Array(..)
var a = new Array( 1, 2, 3 );
a; // [1, 2, 3]
var b = [1, 2, 3];
b; // [1, 2, 3]
构造函数Array(..) 不要求必须带new 关键字。不带时,它会被自动补上。
因此Array(1,2,3) 和new Array(1,2,3) 的效果是一样的。

Array 构造函数只带一个数字参数的时候,该参数会被作为数组的预设长度(length),而非只充当数组中的一个元素。
这实非明智之举:一是容易忘记,二是容易出错。
更为关键的是,数组并没有预设长度这个概念。这样创建出来的只是一个空数组,只不过它的length 属性被设置成了指定的值。
如若一个数组没有任何单元,但它的length 属性中却显示有单元数量,这样奇特的数据结构会导致一些怪异的行为。而这一切都归咎于已被废止的旧特性(类似arguments 这样的类数组)。
3.4.2 Object(..)、Function(..) 和RegExp(..)
同样,除非万不得已,否则尽量不要使用Object(..)/Function(..)/RegExp(..):
var c = new Object();
c.foo = “bar”;
c; // { foo: “bar” }
var d = { foo: “bar” };
d; // { foo: “bar” }
var e = new Function( “a”, “return a * 2;” );
var f = function(a) { return a * 2; }
function g(a) { return a * 2; }
var h = new RegExp( “^a*b+”, “g” );
var i = /^a*b+/g;
在实际情况中没有必要使用new Object() 来创建对象,因为这样就无法像常量形式那样一次设定多个属性,而必须逐一设定。

构造函数Function 只在极少数情况下很有用,比如动态定义函数参数和函数体的时候。不要把Function(..) 当作eval(..) 的替代品,你基本上不会通过这种方式来定义函数。

强烈建议使用常量形式(如/^a*b+/g)来定义正则表达式,这样不仅语法简单,执行效率也更高,因为JavaScript 引擎在代码执行前会对它们进行预编译和缓存。与前面的构造函数不同,RegExp(..) 有时还是很有用的,比如动态定义正则表达式时:
var name = “Kyle”;
var namePattern = new RegExp( “\\b(?:” + name + “)+\\b”, “ig” );
var matches = someText.match( namePattern );
上述情况在JavaScript 编程中时有发生,这时new RegExp(“pattern”,”flags”) 就能派上用场。
3.4.3 Date(..) 和Error(..)
相较于其他原生构造函数,Date(..) 和Error(..) 的用处要大很多,因为没有对应的常量形式来作为它们的替代。
创建日期对象必须使用new Date()。Date(..) 可以带参数,用来指定日期和时间,而不带参数的话则使用当前的日期和时间。
Date(..) 主要用来获得当前的Unix 时间戳(从1970 年1 月1 日开始计算,以秒为单位)。该值可以通过日期对象中的getTime() 来获得。
从ES5 开始引入了一个更简单的方法,即静态函数Date.now()。
如果调用Date() 时不带new 关键字,则会得到当前日期的字符串值。其具体格式规范没有规定,浏览器使用”Fri Jul 18 2014 00:31:02 GMT-0500 (CDT)”这样的格式来显示。

构造函数Error(..)(与前面的Array() 类似)带不带new 关键字都可。
创建错误对象(error object)主要是为了获得当前运行栈的上下文(大部分JavaScript 引擎通过只读属性.stack 来访问)。栈上下文信息包括函数调用栈信息和产生错误的代码行号,以便于调试(debug)。
除Error(..) 之外, 还有一些针对特定错误类型的原生构造函数, 如EvalError(..)、 RangeError(..)、 ReferenceError(..)、 SyntaxError(..)、TypeError(..) 和URIError(..)。这些构造函数很少被直接使用,它们在程序发生异常(比如试图使用未声明的变量产生ReferenceError 错误)时会被自动调用。
3.4.4 Symbol(..)
ES6 中新加入了一个基本数据类型 ——符号(Symbol)。符号是具有唯一性的特殊值(并非绝对),用它来命名对象属性不容易导致重名。该类型的引入主要源于ES6 的一些特殊构造,此外符号也可以自行定义。
符号可以用作属性名,但无论是在代码还是开发控制台中都无法查看和访问它的值,只会显示为诸如Symbol(Symbol.create) 这样的值。
ES6 中有一些预定义符号,以Symbol 的静态属性形式出现,如Symbol.create、Symbol.
iterator 等,可以这样来使用:obj[Symbol.iterator] = function(){ /*..*/ };
我们可以使用Symbol(..) 原生构造函数来自定义符号。但它比较特殊,不能带new 关键字,否则会出错:
var mysym = Symbol( “my own symbol” );
mysym; // Symbol(my own symbol)
mysym.toString(); // “Symbol(my own symbol)”
typeof mysym; // “symbol”

var a = { };
a[mysym] = “foobar”;

Object.getOwnPropertySymbols( a );
// [ Symbol(my own symbol) ]
虽然符号实际上并非私有属性(通过Object.getOwnPropertySymbols(..) 便可以公开获得
对象中的所有符号),但它却主要用于私有或特殊属性。很多开发人员喜欢用它来替代有下划线(_)前缀的属性,而下划线前缀通常用于命名私有或特殊属性。
符号并非对象,而是一种简单标量基本类型。
摘自:《你不知道的javascript》中卷

javascript封装对象的疑惑点

使用封装对象时有些地方需要特别注意。

比如Boolean:

var a = new Boolean( false );

if (!a) {

console.log( “Oops” ); // 执行不到这里

}

我们为false 创建了一个封装对象,然而该对象是真值(“truthy”,即总是返回true,参见第4 章),所以这里使用封装对象得到的结果和使用false 截然相反。

如果想要自行封装基本类型值,可以使用Object(..) 函数(不带new 关键字):

var a = “abc”;

var b = new String( a );

var c = Object( a );

typeof a; // “string”

typeof b; // “object”

typeof c; // “object”

b instanceof String; // true

c instanceof String; // true

Object.prototype.toString.call( b ); // “[object String]”

Object.prototype.toString.call( c ); // “[object String]”

再次强调,一般不推荐直接使用封装对象(如上例中的b 和c),但它们偶尔也会派上用场。

摘自 《你不知道的JavaScript》中卷