乐趣区

关于程序员:JavaScript语言精粹学习笔记

JavaScript 语言精粹学习笔记

语法

1、正文
JS 提供了两种正文形式:一种是块正文:/ 被正文的内容 /,另一种是行正文:// 被正文的内容。
应用块正文是不平安的,例如,应用正则表达式:

// /*
    var test = /test*/;
// */

2、数字

var isNaN = isNaN(number); // 用 isNaN 办法判断是否为数字,不是数字返回 true, 反之,返回 false

3、字符串不可变

'A' === '\u0041'; // true
'c' + 'a' + 't' === 'cat'; // true
'cat'.toUpperCase() === 'CAT'; // true

4、语句
条件判断会被当成 false 的值:false,null,undefined,”,0,NaN, 其余所有值都为被当做 true。

5、运算符
typeof 运算符产生的值有:’number’,’string’,’boolean’,’undefined’,’function’,’object’.
‘+’ 加号的转换规则优先思考字符串连贯,如果其中一个操作数是字符串或者转换为字符串的对象,另一个操作数将会转换为字符串,加法将进行字符串的连贯操作。如果两个操作数都不是类字符串(string-like)的,那么都将进行算术加法运算。

1 + 2 // 3
1 + '2' // '12'
'1' + '2' // '12'
1 + {} // '1[object Object]'
1 + [] // '1'
1 + [1] // '11'
true + true // 2
2 + null // 2
2 + undefined // NaN

‘/’ 运算符可能产生一个非整数后果,即便两个运算数都是整数。
‘&&’ 运算符应用技巧:当 && 的第一个运算数的值为假时,取第一个运算数的值,反之,取第二个的值。

0 && 1; // 0
false && true; // false
true && false; // false
1 && 2; // 2

|| 运算符应用技巧:当第一个运算数的值为为真时,取第一个运算数的值,反之,取第二个的值。个别应用这种技巧设置默认值。

undefined || 0; //0
null || {}; // {}
0 || []; // []
1 || true; // 1

以上技巧利用了 && 和 || 的短路原理,&& 运算符右边的值为假时,不再执行左边的值,|| 运算符右边的值为真,则不再执行左边的值。

对象

1、应用字面量创建对象
对象属性值能够应用 undefined 以外的任何值

var obj = {};
obj.name = 'Better';
obj.age = 24;
obj['first-name'] = 'liao'; // 因为 first-name 不是非法的标识符,所以必须应用 [],不能应用.
obj.last_name = 'longdong'; // last_name 为非法标识符 

2、援用
对象通过援用进行传递

var a = {}, b ={}, c = {}; //a,b,c 属于不同的对象,因为它们的援用不同
a == b; // false
a.name = 'Better';
b.name = 24;
console.log(a); // {name: 'Better'}
console.log(b); // {name: 24}

var a = b = c = {}; // a,b,c 属于同一个对象,因为它们的援用(地址)雷同
a === b; // true
a.name = 'Better';
b.age = 24;
console.log(a); // {name: 'Better', age: 24}
console.log(b); // {name: 'Better', age: 24}

3、原型
每个对象都有原型对象,所谓的原型链,就是查找对象的属性和办法时,首先,查找对象自身是否有该属性或者办法,如果没有,则沿着原型对象进行查找,直到 Object.prototype,如果都没有则返回 undefined.

// 模仿 Object.create() 办法创立新对象
if(typeof Object.create === 'function'){Object.create = function (obj) {var F = function(){};
        F.prototype = obj;
        return new F();}
}
obj.hasOwnProperty('name'); // 该办法用于检测对象自身是否领有该属性,不会查找原型链中的属性和办法 

4、全局变量
缩小全局变量次要有两种形式:一、应用命名空间,二、应用闭包

// 应用命名空间
var mynamespace = {};
mynamespace.module1 = {
    name : 'xiaoxin',
    age: 24
};
mynamespace.module2 = {
    name: 'xiaowu',
    age: 22
};
// 应用闭包,创立惟一 ID
var create = function(){
    var num = 0;
    return function(){return num ++;}
}
var uId = create();
uId(); // 0
uId(); // 1
uId(); // 2

函数

在 JavaScript 中函数就是对象。对象字面量产生的对象连接到 Object.prototype,函数对象连接到 Funtion.prototype(该原型对象自身连贯到 Object.prototype)。
每个函数在创立时两个附加暗藏属性:函数的上下文和实现函数行为的代码。每个函数对象在创立时也带有一个 prototype 属性,它的值是一个领有 constructor 属性,该属性指向该函数对象。

var f = function(){};
f.prototype.constructor === f; // true

1、函数字面量(函数表达式)
函数表达式与函数申明的区别:

// 函数表达式
console.log(fun1); // undefined
var fun1 = function(){console.log(123);
};
console.log(fun1); // function(){console.log(123)};

// 函数申明
console.log(fun2); // function fun2(){console.log(456)};
function fun2(){console.log(456);
};
console.log(fun2); // function fun2(){console.log(456)};

var fun3 = function(){console.log(666);
};
function fun3(){console.log(888);
};
console.log(fun3()); // 666
// 论断:1、函数表达式和函数申明都会进行变量晋升,函数表达式只晋升申明的变量,不会晋升函数体,而函数申明会晋升函数名和函数体;2、函数表达式会笼罩同名的函数申明 

2、函数调用
JavaScript 中一共有四种函数调用模式:办法调用模式、函数调用模式、结构函数调用模式和 apply 调用模式。

  • 办法调用模式
    当函数作为一个对象的办法(属性)时,this 指向该对象。
var myObj = {}; // 创立一个对象
myObj.name = 'Better';
myObj.method = function(){ // 给对象增加办法
    console.log(this.name);
};
myObj.method(); // 'Better'
  • 函数调用模式
    当一个函数没有作为一个对象的办法(属性)时,this 指向全局对象(window 对象)
// 全局函数
function add(a, b){return a + b;};
add(1, 2); // 3

myObj.value = 2;
myObj.double = function(){console.log(this);
    var that = this; // 把指向 myObj 对象的 this 指针,存到 that 变量中
    var helper = function(){console.log(this); // 这里的 this 指向 window 对象
        that.value = add(that.value, that.value);
    };
    helper(); // 以函数模式进行调用 helper 函数};
myObj.double(); // 以办法的模式调用 double 函数
myObj.value; // 4
  • 结构函数调用模式
    如果函数后面带上 new 来调用,那么 this 指向该新对象上,应用 new 调用函数也会扭转 return 语句的行为,如果 return 的是对象则返回该对象,否则,返回(this)新创建的对象。
// 创立一个构造函数,约定构造函数应用大写结尾
function Fun(string){this.status = string;};
// 给构造函数增加公共办法
Fun.prototype.getStatus = function(){return this.status;};
// 创立实例
var fun = new Fun('Better');
fun.getStatus(); // 'Better'
// 不举荐应用该办法 
  • apply 调用模式
    apply 办法有两个参数,第一个参数 thisObj,是绑定 this 执行的上下文,第二个参数 argArr,参数数组。
// 创立一个构造函数,约定构造函数应用大写结尾
function Fun(string){this.status = string;};
// 给构造函数增加公共办法
Fun.prototype.getStatus = function(){return this.status;};
// 创立实例
var fun = new Fun('Better');
fun.getStatus(); // 'Better'

// this 指向全局对象
function add(a, b){return a + b;};
var arr = [3, 4];
var sum = add.apply(null, arr); // 7

// this 指向 obj 对象
var obj = {};
obj.status = 24;
Fun.prototype.getStatus.apply(obj); // 24
fun.getStatus.apply(obj); // 24
fun.getStatus.apply(this);

// apply 办法第一个参数为 null 或者 undefined 时,this 指向全局对象(非严格模式下)function test(){console.log(this);
};
test.apply(null); // this 指向全局对象(window 对象)test.apply(undefined); // this 指向全局对象(window 对象)test.apply(this); // this 指向全局对象(window 对象)test.apply(1); // this 指向 Number 对象
test.apply('string'); // this 指向 String 对象
test.apply(true); // this 指向 Boolean 对象

// 论断:艰深的说,就是把某个办法放到 apply 办法的第一个参数(thisObj)作用域下执行。

3、arguments 类数组参数对象
arguments 对象是一个类数组对象,只有 length 属性,没有数组相干办法。它能够获取函数调用时的参数列表。该对象只能在函数外部应用。

var sum = function(){
    var sum = 0;
    for(var i = 0, len = arguments.length; i < len; i ++){sum += arguments[i];
    }
    return sum;
};
console.log(sum(1, 2, 3, 4, 5)); // 15

4、异样
JavaScript 提供了一套异样解决机制。

var add = function(a, b){if(typeof a !== 'number' || typeof b !== 'number'){
        throw {
            name: 'TypeError',
            message: 'add needs numbers'
        };
    }
    return a + b;
};
add(1, 2); // 3
add(1, '2'); // 报错
add(); // 报错

// try_catch 代码块
var try_it = function(){
    try{add('one');
    }catch(e){console.log(e.name + ':' + e.message);
    }
};
try_id(); // TypeError : add needs numbers

5、给类型增加办法
通过给 Object.prototype 增加办法使得该办法对所有对象可用。
通过给 Function.prototype 增加办法使得该办法对所有函数可用。

// 给 Function.prototype 增加办法
Function.prototype.method = function(name, func){if(!this.prototype[name]){this.prototype[name] = func;
    }
};

// 给 Number 对象增加一个 integer 办法
Number.method('integer', function(){
    var funName = this < 0 ? 'ceil' : 'floor'; 
    return Math[funName](this);
});
(10/4).integer(); // 2
(-10/4).integer(); // -2

// 给 String 对象增加一个移除两端字符串的办法
String.method('trim', function(){return this.replace(/^\s+|\s+$/, '');
});
'Better'.trim(); // 'Better'

6、递归
递归函数会间接或间接地调用本身的一种函数。一般来说,一个递归函数调用本身去解决它的子问题。
递归能够十分高效地操作树形构造,比方浏览器端的文档对象模型(DOM)。每次递归调用时解决给定树的一小段。

// walk_the_DOM 调用本身去解决每一个子节点
var walk_the_DOM = function walk(node, func){func(node);
    node = node.firstChild;
    while(node){walk(node, func);
        node = node.nextSibling;
    }
};
// 创立一个通过属性查找节点的函数
var getElementByAttribute = function(attr, value){var results = [];
    walk_the_DOM(document.body, function(node){var actual = node.nodeType === 1 && node.getAttribute(attr);
        if(typeof actual === 'string' && (actual === value || typeof value !== 'string')){results.push(node);
        }
    });
    return results;
};

// 利用递归,计算一个数的阶乘
var factorial = function factorial(i, a){
    a = a || 1;
    if(i < 2){return a;}
    return factorial(i - 1, a * i);
};
factorial(3); // 6
factorial(3, 2); // 12
factorial(3, 3); // 18

// 不倡议在匿名函数中应用 arguments.callee()
// 在给函数表达式一个名称或者应用函数申明而该函数必须调用本人时,禁止应用 arguments.callee()
// 在 ES5 的严格模式中禁止应用 arguments.callee()
function create(){return function(num){if(num < 2){return 1;}else{return num * arguments.callee(num - 1);
        }
    }    
};
var result = create()(3); // 6

7、作用域
作用域管制着变量与参数的可见性和生命周期。
JavaScript 有函数作用域,但没有块级作用域,最好的做法是在函数体的顶部申明函数中可能用到的所有变量。

// 函数内的变量会进行变量晋升,所以运行 cxt() 函数,前两次 console.log(c); 没有报错
function cxt(){
    var a = 1, b = 2;
    console.log(c); // undefined
    function innerFun(){
        var a = 6, b =7, c = 8;
        console.log(a, b, c); // 6 7
    }
    innerFun();
    console.log(c); // undefined
    if(a == 1){ // false
        var c = 3;
    };
    console.log(c); // 3
}

8、闭包
闭包是指有权拜访另一个函数作用域中的变量的函数,创立闭包的最常见的形式就是在一个函数内创立另一个函数,通过另一个函数拜访这个函数的局部变量。

var myObject = function(){
    var value = 0;
    return {increment: function(inc){value += typeof inc === 'number' ? inc : 1;},
        getValue: function(){return value;}
    };
}();

// 创立一个名为 quo 的构造函数
var quo = function(status){
    return {getStatus: function(){return status;}
    };
};
// 结构一个 quo 实例
var myQuo = quo('crazy');
console.log(myQuo.getStatus()); // 'crazy'
// 这个构造函数被设计成无需加 new 来应用,所以名字也没有首字母大写

// 定义一个函数,它设置一个 DOM 节点为黄色,而后把它突变为红色
var fade = function(node){
    var level = 1;
    var step = function(){var hex = level.toString(16); // 转化为 16 进制数
        console.log(hex);
        node.style.backgroundColor = '#FFFF' + hex + hex;
        if(level < 15){
            level += 1;
            setTimeout(step, 100);
        }
    };
    setTimeout(step, 100);
};
fade(document.body);

9、回调
回调函数能够让不间断的事件处理变得更容易。

// 这种同步申请会阻塞过程
request = prepare_the+request();
response = send_request_synchronously(request);
display(response);

// 更好的形式应用异步回调申请
request = prepare_the_request();
send_request_asynchronously(request, function(response){display(response);
});

10、模块
能够应用函数和闭包来结构模块。
模块是一个提供接口却暗藏状态与实现的函数或对象。
模块模式的个别模式:一个定义了公有变量和函数的函数;利用闭包创立能够拜访公有变量和函数的特权函数;最初返回这个特权函数,或者把它们保留到一个可拜访的中央。

// 给所有函数都增加该办法
Function.prototype.method = function(name, func){if(!this.prototype[name]){this.prototype[name] = func;
    }
}
String.method('deentityify', function(){
    // 字符实体表
    var entity = {
        quot: '""',
        lt: '<',
        gt: '>'
    };
    // 返回 deentityify 办法
    return function(){
        // 应用字符串的 replace 办法
        // 查找‘&’结尾和‘;’完结的子字符串
        return this.replace(/&([^&;]+);/g, function(a, b){console.log(a, b); // a 为正则表达式第一个匹配,b 为第二个匹配(正则表达式圆括号里的匹配)var r = entity[b];
            return typeof r === 'string' ? r : a;
        });
    }
}()); // 这里应用立刻执行函数
console.log('&lt;&quot;&gt;'.deentityify()); // <"">

// 结构一个用来产生序列号的对象
var serial_marker = function(){
    // 返回一个用来产生惟一字符串的对象
    // 惟一字符串由两局部组成:前缀 + 序列号
    // 该对象蕴含一个设置前缀的办法,一个设置序列号的办法和一个产生惟一字符串的 gensym 办法
    var prefix = '';
    var seq = 0;
    return {set_prefix: function(p){prefix = String(p);
        },
        set_seq: function(s){seq = s;},
        gensym: function(){
            var result = prefix + seq;
            seq += 1;
            return result;
        }
    };
};
var seqer = serial_marker();
seqer.set_prefix('Q');
seqer.set_seq(1000);
var unique = seqer.gensym(); // unique is "Q1000"
var unique = seqer.gensym(); // "Q1001"

模块模式通常联合单例模式(Singleton Pattern)应用。
JavaScript 的单例就是用对象字面量表示法创立的对象,对象的属性值能够是数值或函数,并且属性值在该对象的生命周期中不会发生变化。

11、链式调用(级联)
办法返回 this 而不是 undefined 就能够启用链式调用(级联),链式调用能够产生出具备弱小表现力的接口。

getElement('myBoxDiv').
    move(100, 200).
    width(100).
    height(200).
    color('red').
    on(mouseover, func);

12、记忆
函数能够用对象去记住先前操作的后果,从而防止多余的运算。这种优化被称为记忆。JavaScript 的对象和数组要实现这种优化是十分不便的。

// Fibonacci 数列,斐波那契数列,特点,后面相邻两项之和等于后一项的值。var fibonacci = function(n){return n < 2 ? n : fibonacci(n - 1)    + fibonacci(n - 2);
};
for(var i =0; i <= 10; i ++){console.log(i, fibonacci(i));
}
// 0 0
// 1 1
// 2 1
// 3 2
// 4 3
// 5 5
// 6 8
// 7 13
// 8 21
// 9 34
// 10 55
// fibonacci 被调用了 453 次,除了咱们调用了 11 次,其它的调用大都在计算曾经计算过的值

// 下面的例子做了很多反复的工作,上面进行一下优化
var fibonacci = function(){var memo = [0, 1];
    var fib = function(n){var result = memo[n];
        if(typeof result !== 'number'){ // 判断是否曾经存在后果
            result = fib(n - 1) + fib(n - 2);
            memo[n] = result;
        }
        return result;
    };
    return fib;
}();
for(var i =0; i <= 10; i ++){console.log(i, fibonacci(i));
}
// 这样优化后只调用了 29 次,咱们调用了 11 次,函数本身调用了 18 次

// 编写一个函数来帮忙咱们结构带记忆动能的函数,他返回一个治理 memo 存储和在须要是调用 func 函数的 shell 函数。var memoizer = function(memo, func){var shell = function(n){var result = memo[n];
        if(typeof result !== 'number'){result = func(shell, n);
            memo[n] = result;
        }
        return result;
    };
    return shell;
};
// 应用 memoizer 来定义 fibonacci 函数
var fibonacci = memoizer([0, 1], function(shell, n){return shell(n - 1) + shell(n - 2);
});
// 应用 memoizer 来定义 factoriala 函数
var factorial = memoizer([1, 1], function(shell, n){return n * shell(n - 1);
});

继承

1、伪类
当一个函数对象被创立时,Function 结构器产生的函数对象会运行相似这样的一些代码:

this.prototype = {constructor: this};

新函数对象被赋予一个 prototype 属性,其值是蕴含一个 constructor 属性且属性值为该新函数对象。每个函数都领有一个 prototype 对象。

function f(){};
f.prototype.constructor === f; // true

定义一个结构器并给原型增加办法

// 父类
// 创立构造函数
var Mammal = function(name){this.name = name;};
// 给原型增加办法
Mammal.prototype.getName = function(){return this.name;};
Mammal.prototype.say = function(){return this.saying || 'hello';};
var myMammal = new Mammal('Herb the Mammal');
var name = myMammal.getName(); // 'Herb the Mammal'

// 子类
var Cat = function(name){
    this.name = name;
    this.saying = 'meow';
};
// 替换 Cat.prototype 为一个新的 Mammal 实例 (继承父类)
Cat.prototype = new Mammal();
// 给新的原型对象增加办法
Cat.prototype.purr = function(n){
    var i, s = '';
    for(i = 0; i < n; i += 1){if(s){s += '-';}
        s += 'r';
    }
    return s;
};
Cat.prototype.getName = function(){return this.say() + '' + this.name +' ' + this.say();};
var myCat = new Cat('Henrietta');
var say =  myCat.say(); // 'meow'
var purr = myCat.purr(5); // 'r-r-r-r-r'
var name = myCat.getName(); // 'meow Henrietta meow'

// 暗藏 prototype 操作细节,这部分代码要用到下面 Mammal 父类代码,能力运行
Function.prototype.method = function(name, func){if(!this.prototype[name]){this.prototype[name] = func;
    }
    return this;
};
Function.method('inherits', function(Parent){this.prototype = new Parent();
    return this;
});
var Cat = function(name){
    this.name = name;
    this.saying = 'meow';
}.
    inherits(Mammal).
    method('purr', function(n){
        var i, s = '';
        for(i = 0; i < n; i += 1){if(s){s += '-';}
            s += 'r';
        }
        return s;
    }).
    method('getName', function(){return this.say() + '' + this.name +' ' + this.say();});
var cat = new Cat('icat');
cat.getName(); // 'icat'
cat.purr(5); // r-r-r-r-r
// 这种办法的毛病:没有公有环境,所有的属性都是公开的。

2、原型

// 创立一个有用的对象
var myMammal = {
    name: 'Herb the Mammal',
    getName: function(){return this.name;},
    says: function(){return this.saying || '';}
};
// 应用 Object.create() 办法结构出更多的实例来
var myCat = Object.create(myMammal);
myCat.name = 'Henrietta';
myCat.saying = 'meow';
myCat.purr = function(n){
    var i, s = '';
    for(i = 0; i < n; i ++){if(s){s += '-';}
        s += 'r';
    }
    return s;
};
myCat.getName = function(){return this.says() + '' + this.name +' ' + this.says();};
// 这是一种“差异化继承”,通过制订一个新的对象,咱们指明了它与所基于的根本对象的区别。

3、函数化
后面的例子中的 name 属性和 saying 属性是齐全公开的,上面这个例子让 name 属性和 saying 属性变成公有变量:

// 模块模式的利用
var mammal = function(spec){var that = {};
    that.getName = function(){return spac.name;};
    that.says = function(){return spec.saying || '';};
    return that;
};
var myMammal = mammal({name: 'Herb'});

var cat = function(spec){
    spec.saying = spec.saying || 'meow';
    var that = mammal(spec);
    that.purr = function(n){
        var i, s = '';
        for(i = 0; n < i; i ++){if(s){s += '-';}
            s += 'r';
        }
        return s;
    };
    that.getName = function(){return that.says() + '' + spec.name +' ' + that.says();};
    return that;
};
var myCat = cat({name: 'Henrietta'});

// 函数化模式给咱们提供了一个解决父类的办法
Function.prototype.method = function(name, func){if(!this.prototype[name]){this.prototype[name] = func;
    }
    return this;
};
Object.method('superior', function(name){
    var that = this;
    method = that[name];
    return function(){return method.apply(that, arguments);
    }
});
var coolcat = function(spec){var that = cat(spec);
    var superGetName = that.superior('getName');
    that.getName = function(){return 'like' + superGetName() + 'baby';
    };
    return that;
};
var myCoolCat = coolcat({name: 'Bix'});
var name = myCoolCat.getName(); // 'like meow Bix meow baby'

4、部件

var eventuality = function(that){var registry = {};
    that.fire = function(event){
        var array,
            func,
            handler,
            i,
            type = typeof event === 'string' ? event : event.type;
        // 如果这个事件存在一组事件处理程序,那么就遍历它们并按程序顺次执行
        if(registry.hasOwnProperty(type)){array = registry[type];
            for(i = 0; i < array.length; i ++){handler = array[i];
                // 每个处理程序蕴含一个办法和一组可选的参数
                // 如果该办法是一个字符串模式的名字,那么寻找到该函数
                func = handler.method;
                if(typeof func === 'string'){func = this[func];
                }
                func.apply(this, handler.parameters || [event]);
            }
        }
        return this;
    };
    that.on = function(type, method, parameters){
        // 注册一个事件,结构一条处理程序条目,将它插入到处理程序数组中,如果这种类型的事件还不存在,就结构一个
        var handler = {
            method: method,
            parameters: parameters
        };
        if(registry.hasOwnProperty(type)){registry[type].push(handler);
        }else{registry[type] = [handler];
        }
        return this;
    };
    return that;
};
// 用这种形式,一个构造函数能够从一套部件中组装出对象来 

数组

数组是一段线性调配的内存,它通过整数去计算偏移并拜访其中的元素。数组能够是很快的数据结构。然而,JavaScript 没有像这种数组一样的数据结构。
JavaScript 提供了一种领有一些类数组(array-like)个性的对象,它把数组的下标转变成字符串,用其作为属性。它的性能显著的比真正的数组慢,但它能够更不便的应用。
1、数组字面量
数组的第一个值将取得属性名 ’0’,第二个将取得属性名 ’1’,顺次类推:

// 数组字面量
var empty = [];
var numbers = ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine'];
console.log(empty[1]); // undefined
console.log(numbers[1]); // 'one'
console.log(numbers['1']); // 'one'
console.log(empty.length); // 0
console.log(numbers.length); // 10

// 对象字面量
var numbers_object = {
    '0': 'zero',
    '1': 'one',
    '2': 'two',
    '3': 'three',
    '4': 'four',
    '5': 'five',
    '6': 'six',
    '7': 'seven',
    '8': 'eight',
    '9': 'nine'
};
// 在大多数语言中,一个数组的所有元素都要求是雷同的类型。然而,JavaScript 容许数组蕴含任意混合类型的值
var misc = ['steing', 66, true, null, undefined, [1, 2, 3], NaN, {name: 'Better'}];

numbers 和 numbers_object 两者的区别:

  • numbers 继承自 Array.prototype,而 numbers_object 继承自 Object.prototype
  • numbers 继承了大量操作数组的办法
  • numbers 有 length 属性,而 numbers_object 则没有

2、长度
JS 数组的 length 属性没有下限,如果你用等于或大于以后 length 的数字作为下标来保留一个元素,那么 length 将增大来包容新元素,不会产生数组越界谬误。

// length 属性的值是这个数组的最大整数属性名加 1,它不肯定等于数组里属性的个数
var myArray = [];
console.log(myArray.length); // 0
// myArray[10000] = true;
myArray['10000'] = true;
console.log(myArray.length); // 10001

// 能够间接设置数组 length 属性的值,设置更大的 length 不会给数组调配更多的空间,// 而把 length 设小将导致所有等于大于新 length 的属性被删除
var numArr = [0, 1, 2, 3, 4, 5];
numArr.length = 3;
console.log(numArr); // [0, 1, 2]

// 增加新元素到数组尾部
numArr[numArr.length] = 3;
console.log(numArr); // [0, 1, 2, 3]

// 增加新元素到数组尾部,应用 push 办法
numArr.push(4);
console.log(numArr); // [0, 1, 2, 3, 4]

3、删除
因为 JavaScript 的数组其实就是对象,所以能够应用 delete 运算符移出数组中的元素,然而数组中会遗留一个空洞。

var numArr = [0, 1, 2, 3, 4, 5];
delete numArr[2];
console.log(numArr); // [0, 1, undefined, 3, 4, 5]

// 应用数组中的 splice() 办法
var numArr = [0, 1, 2, 3, 4, 5];
// 从数组下标为 2 的地位开始,删除 1 个数组元素,// 并在该地位插入 66 这个元素,返回被删除的元素数组 [2]
numArr.splice(2, 1, 66); // [2]
console.log(numArr); // [0, 1, 66, 3, 4, 5]

4、枚举
因为 JS 中的数组也是对象,所有能够应用 for in 语句来遍历数组的所有属性。
然而,应用 for in 语句无奈保障属性的程序,而且存在从原型链中失去意外属性的可能

// 应用 for in 遍历数组的属性(不举荐)var nums = ['zero', 'one', 'two', 'three'];
for(var num in nums){console.log(num, nums[num]);
}
// 举荐应用 for 循环遍历数组
for(var i = 0, len = nums.length; i < len; i ++){console.log(i, nums[i]);
}

5、判断数组(包含其它类型)

// 本书中应用的办法(数组中的 length 不可枚举,length 是否通过 for in 遍历进去?)var arr = [];
var obj = {};
var is_array = function(value){
    return value &&  // 判断这个值是否为真
        typeof value === 'object' &&  // 是否为对象
        typeof value.length === 'number' &&  // 是否存在 length 属性而且值为数字类型
        typeof value.splice === 'function' &&  // 是否存在 splice 办法
        !(value.propertyIsEnumerable('length'));  // length 属性是否可枚举
};
console.log(is_array(arr)); // true
console.log(is_array(obj)); // false

// 判断一个值是否为数组(最罕用的办法)function isArray(value){return Object.prototype.toString.call(value) === '[object Array]';
}
var arr = [];
var num = 1;
var bool = true;
var str = 'string';
var obj = {};
var func = function(){};
console.log(isArray(arr)); // true
console.log(Object.prototype.toString.call(num)); // '[object Number]'
console.log(Object.prototype.toString.call(bool)); // '[object Boolean]'
console.log(Object.prototype.toString.call(str)); // '[object String]'
console.log(Object.prototype.toString.call(obj)); // '[object Object]'
console.log(Object.prototype.toString.call(func)); // '[object Function]'
console.log(Object.prototype.toString.call(null)); // '[object Null]'
console.log(Object.prototype.toString.call(undefined)); // '[object Undefined]'
// PS: 应用该办法的前提是 Object 对象的 toString() 办法没有被重写 

6、办法
JS 提供了一套用于操作数组的办法,这些办法被寄存在 Array.prototype 中,咱们能够通过在 Array.prototype 中增加办法来裁减数组办法

// 裁减一个办法,每个数组都会继承这个办法
Array.prototype.reduce1 = function(func, value){for(var i =0, len = this.length; i < len; i ++){value = func(this[i], value);
    }
    return value;
};
var arr = [1, 2, 3, 4, 5];
var add = function(a, b){return a + b;};
var mult = function(a, b){return a * b;};
var sum = arr.reduce1(add, 0); // 15
var product = arr.reduce1(mult, 1); // 120

// 因为数组也是对象,所以能够独自给数组增加办法
arr.total = function(){return this.reduce1(add, 0);
};
total = arr.total(); // 15

7、维度

// 定义一个初始化数组的办法
Array.dim = function(dimension, initial){var a = [], i;
    for(i = 0; i < dimension; i ++){a[i] = initial;
    }
    return a;
}
// 创立一个蕴含 6 个 6 的数组
var myArray = Array.dim(6, 6); // [6, 6, 6, 6, 6, 6]

// 多维数组
var matrix = [[0, 1, 2],
    [3, 4, 5],
    [6, 7, 8]
];
matrix[2][0]; // 6

// 数组矩阵
Array.matrix = function(m, n, initValue){var i, j, a, mat = [];
    for(i = 0; i < m; i ++){a = [];
        for(j = 0; j < n; j ++){a[j] = initValue;
        }
        mat[i] = a;
    }
    return mat;
}
// 创立一个用 6 填充的 4×4 矩阵
var myMatrix = Array.matrix(4, 4, 6);
console.log(myMatrix[3][3]); // 6

// 创立一个恒等矩阵
Array.identity = function(n){var i, mat = Array.matrix(n, n, 6);
    for(i =0; i < n; i ++){mat[i][i] = 8
    }
    return mat;
}
var myMatrix1 = Array.identity(4);
console.log(myMatrix1[3][2]); // 6
console.log(myMatrix1[3][3]); // 8

正则表达式

正则表达式是一门简略语言的语法标准,它以办法的模式被用于对字符串中的信息进行查找、替换和提取操作。
解决正则表达式的办法次要有:regexp.exec、regepx.test、string.match、string.replace、string.search、string.split。

正则表达式罕用字符阐明:

  • 点字符:. 匹配除回车(\r)、换行 (\n)、行分隔符(\u2028)和段分隔符(\u2029)以外的所有字符。
  • 地位字符:^ 示意字符串的开始地位,$ 示意字符串的完结地位。
  • 抉择字符:| 示意“或”,如,a|b,示意匹配 a 或 b。
  • 本义符:\ 用来本义正在表达式中有非凡含意的字符,如 +、-、? 等,如,\+,示意匹配 +。
  • 脱字符:1 示意匹配除 a、b、c 之外的任意字符。
  • 连字符:[0-9] 示意匹配 0~9 的数字。[A-Z] 示意匹配 A 到 Z 的 26 个大写字母。
  • 预约义模式:
  • 反复类:{n,m} 示意反复不少于 n 次,不多于 m 次。
  • 量词符:
    1、a? 示意匹配 a 呈现 0 次或 1 次,等同于 a{0,1}。
    2、a* 示意匹配 a 呈现 0 次或屡次,等同于 a{0,}。
    3、a+ 示意匹配 a 呈现 1 次或屡次,等同于 a{1,}。
  • 贪心模式:默认状况下都是最大可能匹配,即匹配直到下一个字符不满足匹配规定为止。这被称为贪心模式。
  • 非贪心模式:
    1、*? 示意某个模式呈现 0 次或屡次,匹配时采纳非贪心模式。
    2、+? 示意某个模式呈现 1 次或屡次,匹配时采纳非贪心模式。
  • 修饰符:
    1、g 修饰符示意全局匹配(global)。
    2、i 修饰符示意疏忽大小写(ignorecase)。
    3、m 修饰符示意多行模式(multiline),会批改 ^ 和 $ 的行为。
  • 组匹配:(abc) 示意组匹配,正则表达式的括号示意分组匹配,括号中的模式能够用来匹配分组的内容。
  • 非捕捉组匹配:(?:abc) 示意非捕捉组匹配,非捕捉组匹配不返回该组匹配的内容,即匹配的后果中不计入这个括号(匹配分组)。
  • 组匹配和非捕捉组匹配的区别:
    1、应用 exec 和 match 办法时会把组匹配放入到 exec 和 match 办法返回的匹配数组(匹配分组)中。
    2、非捕捉组匹配性能要比组匹配性能好。

1、例子

// 匹配 URL 的正则表达式
var parse_url = /^(?:([A-Za-z]+):)?(\/{0,3})([0-9.\-A-Za-z]+)(?::(\d+))?(?:\/([^?#]*))?(?:\?([^#]*))?(?:#(.*))?$/;

var url = 'http://www.better.com:8080/goodparts?q#fragment';

// 应用正则表达式的 exec() 办法,该办法返回一个匹配数组
var result_arr = parse_url.exec(url);
var names = ['url', 'scheme', 'slash', 'host', 'port', 'path', 'query', 'hash'];
var line_end = '\n';
var i;
for(i = 0, len = names.length; i < len; i ++){console.log(names[i] + ':' + result_arr[i] + line_end);
}
// 输入后果:// url : http://www.better.com:8080/goodparts?q#fragment
// scheme : http
// slash : /
// host : www.better.com
// port : 8080
// path : goodparts
// query : q
// hash : fragment

// 匹配数字的正则表达式
var parse_num = /^-?\d+(?:\.\d*)?(?:e[+\-]?\d+)?$/i;
var test_num = function(num){return parse_num.test(num);
}
console.log(test_num('1')); // true
console.log(test_num('-1')); // true
console.log(test_num('0.01')); // true
console.log(test_num('0.')); // true
console.log(test_num('1.2.3')); // false
console.log(test_num('123.45e-67')); // true
console.log(test_num('123.45E+67')); // true
console.log(test_num('123.456D-7')); // false
// 通常用非捕捉型分组来代替大量不柔美的捕捉型分组是很好的办法
// 因为捕捉会有性能上的损失。

2、构造
正则表达式有两种创立形式:

// 最罕用的形式(字面量)var reg = /^\d+$/g;
console.log(reg.test(123)); // true
console.log(reg.test('123s')); // false

// 应用 RegExp 结构器,这时的反斜杠(\)和字面量中有不同的含意
// 通常须要双写反斜杠进行本义
var reg = new RegExp('^\\d+$', 'g');
console.log(reg.test(123)); // true
console.log(reg.test('123s')); // false

办法

JavaScript 有不少内置对象,比方,Array,Date,RegExp,Error,Math 以及根本数据类型的封装对象,Number,Boolean,String 等,这些内置对象都提供许多操作该类型的属性和办法,这些办法寄存在内置对象中或者内置对象的原型对象中。

1、Array

// array.concat(item...) 办法,连贯数组
var a = [1, 2, 3];
var b = ['a', 'b', 'c'];
var c = a.concat(b, true); // [1, 2, 3, "a", "b", "c", true]

// array.join(separator) 办法,该办法性能优于 + 运算符连贯字符串
var a = ['a', 'b', 'c'];
var c = a.join('@'); // "a @ b @ c"

// array.pop() 办法,移出数组中最初一个元素,如果数组为空,则该办法返回 undefined。// array.pop() 办法和 array.push() 办法组合应用能够模仿后进先出队列
var a = ['a', 'b', 'c'];
var c = a.pop(); // 'c'
console.log(a); // ['a', 'b']

// 实现 pop() 办法
Array.prototype.pop = function(){return this.splice(this.length - 1, 1)[0];
};

// array.push(item...) 办法,在数组开端增加元素
var a = [1, 2, 3];
var b = ['a', 'b', 'c'];
var c = a.push(b, true); // 5,返回新数组的长度
console.log(a); // [1, 2, 3, ['a', 'b', 'c'], true]

// 实现 push() 办法
Array.prototype.push = function(){
    // 把 push 办法的参数增加到 splice 办法的第三个参数中
    this.splice.apply(this, [this.length, 0].concat(Array.prototype.slice.apply(arguments)));
    return this.length;
};

// array.reverse() 办法,反转数组中元素的程序。var a = [1, 2, 3];
var b = a.reverse(); // [3, 2, 1]

// array.shift() 办法,移出数组中的第一个元素,如果数组为空,则该办法返回 undefined。// shift 办法通常比 pop 办法慢得多
var a = [1, 2, 3];
var b = a.shift(); // 1
console.log(a); // [2, 3]

// 实现 shift 办法
Array.prototype.shift = function(){return this.splice(0, 1)[0];
};

// array.slice(startIndex, endIndex) 办法,截取数组
var a = [1, 2, 3];
console.log(a.slice(0, 1)); // [0]
console.log(a.slice(1)); // [2, 3]
console.log(a.slice(1, 3)); // [2, 3]

// array.sort(comparefn) 办法, 对数组进型排序
// 不传比拟函数,默认的比拟函数会把所有元素转化为字符串而后再进行比拟
var a = [3, 1, 5, 23, 16, 8];
console.log(a.sort()); // [1, 16, 23, 3, 5, 8]

// 应用比拟函数
var a = [3, 1, 8, 5, '4', 23, 16, 8];
var compareFun = function(a, b){return a - b;};
console.log(a.sort(compareFun)); // [1, 3, "4", 5, 8, 8, 16, 23]

// array.splice(startIndex, delCount, insertItem)
var a = [1, 2, 3, 4, 5];
var b = a.splice(2, 1, 6, 6); // [3] , 返回被移除的元素数组
console.log(a); // [1, 2, 6, 6, 4, 5]

var a = [1, 2, 3, 4, 5];
var b = a.splice(2, 1, [6, 6]); // [3] , 返回被移除的元素数组
console.log(a); // [1, 2, [6, 6], 4, 5]

// array.unshift(item...) 办法,把元素增加到数组的首部
var a = [1, 2, 3, 4];
var b = a.unshift(0); // 5,返回新数组的长度
console.log(a); // [0, 1, 2, 3, 4]

// 实现 unshift() 办法
Array.prototype.unshift = function(){this.splice.apply(this, [0, 0].concat(Array.prototype.slice.apply(arguments)));
    return this.length;
};

操作数组的办法都寄存在 Array.prototype 原型对象中,其中,包含 ES5 和 ES6 新增的数组办法,如 forEach,reduce,map,entries,every,some 等办法。

2、Function
函数对象有两个比拟罕用的办法:apply 和 call 办法。这个两个办法的区别是:前者的参数是以数组的模式传递,而后者这是单个单个的传递。
func.apply(thisArg, argArray),该办法的第一个参数:将 func 办法放到 thisArg 作用域下执行,也就是说,将 func 办法的 this 指向 thisArg,第二个参数(可选):要传递给 func 办法的参数数组。func.call(thisArg, arg1, arg2, …)。

// 利用 apply 办法实现 bind 办法
Function.prototype.bind = function(that){
    // 返回一个函数,调用这个函数就像它是 that 对象的办法一样
    var self = this;
    console.log('self:', self);
    var slice = Array.prototype.slice;
    console.log('arguments:', arguments);
    var args = slice.apply(arguments, [1]);
    return function(){return self.apply(that, args.concat(slice.apply(arguments, [0])));
    };
};

var test = function(){return this.value;}.bind({value: 'Better'});
console.log(test()); // 'Better'

3、Number
Number 对象提供了很多操作数字的办法。这些属性和办法寄存在 Number 对象或者 Number.prototype 原型对象中。

// number.toExponential(fractionDigits),该办法把 number 转换成一个指数模式的字符串。console.log(Math.PI.toExponential()); // 3.141592653589793e+0
console.log(Math.PI.toExponential(0)); // 3e+0
console.log(Math.PI.toExponential(2)); // 3.14e+0

// number.toFixed(fractionDigits),该办法把 number 转换成一个十进制模式的字符串。console.log(Math.PI.toFixed()); // 3
console.log(Math.PI.toFixed(0)); // 3
console.log(Math.PI.toFixed(2)); // 3.14

// number.toPrecision(precision),该办法把 number 转换成一个十进制模式的字符串,precision 是有效数字的位数
console.log(Math.PI.toPrecision()); // 3.141592653589793
console.log(Math.PI.toPrecision(2)); // 3.1
console.log(Math.PI.toPrecision(4)); // 3.142

// number.toString(radix),该办法把 number 转换成一个字符,radix 示意进制基数
console.log(Math.PI.toString()); // 3.141592653589793
console.log(Math.PI.toString(2)); // 11.001001000011111101101010100010001000010110100011
console.log(Math.PI.toString(8)); // 3.1103755242102643
console.log(Math.PI.toString(16)); // 3.243f6a8885a3

4、Object

// object.hasOwnProperty(name),该办法用来查看某个对象是否蕴含某个属性或者办法,// 该办法不会检测原型链中的属性和办法
var obj1 = {member: true};
var obj2 = Object.create(obj1);
console.log(obj1.hasOwnProperty('member')); // true
console.log(obj2.hasOwnProperty('member')); // false
console.log(obj2.member); // true

5、RegExp

  • regexp.exec(string) 办法是正则表达式中最弱小(和最慢)的办法。如果它胜利的匹配,它会返回一个数组。数组中下标为 0 的元素将蕴含正则表达式 regexp 匹配的子字符串。下标为 1 的元素是分组 1 捕捉的文本,下标为 2 的元素是分组 2 捕捉的文本,顺次类推。如果匹配失败,则返回 null。
  • regexp.test(string) 办法是正则表达式中最简略(和最快)的办法。如果匹配胜利,返回 true,否则,返回 false。不要对这个办法应用 g 标识。
// regexp.exec(string),匹配邮箱
var regexpEmail = /^(\w+)@(\w+\.\w{2,4})$/;
var QQEmail = '924902324@qq.com';
var gmail = 'liaolongdong@gmail.com';
console.log(regexpEmail.exec(QQEmail));

// 0: "924902324@qq.com"
// 1: "924902324"
// 2: "qq.com"
// index: 0
// input: "liaolongdong@gmail.com"

console.log(regexpEmail.exec(gmail));

// 0: "liaolongdong@gmail.com"
// 1: "liaolongdong"
// 2: "gmail.com"
// index: 0
// input: "liaolongdong@gmail.com"

// regexp.test(string)
var a = /&.+;/.test('Better &amp; Beans'); // true

// 实现 test 办法
RegExp.prototype.test = function(string){return this.exec(string) !== null;
};

6、String
操作字符串的办法大多数都寄存在 String.prototype 原型对象中

// string.charAt(pos) 办法,返回 string 中 pos 地位的字符
var name = 'Better';
console.log(name.charAt(-1)); // ''console.log(name.charAt(1)); //'e'console.log(name.charAt(8)); //''

// 实现 charAt 办法
String.prototype.charAt = function(pos){return this.slice(pos, pos + 1);
};

// string.charCodeAt(pos) 办法,返回 string 中 pos 地位处的字符的字符编码。var name = 'Better';
console.log(name.charCodeAt(-1)); // NaN
console.log(name.charCodeAt(1)); // 101
console.log(name.charCodeAt(name.length)); // NaN

// string.concat(string...) 办法,把字符串连接起来结构一个新字符串
// 这个办法比拟少用,因为连贯字符串应用 + 运算符更不便
var str = 'B'.concat('i', 'g'); // 'Big'

// string.indexOf(searchString, position),在 string 中查找另一个字符串 searchString
// 如果查找到,返回第一个匹配字符的地位,否则,返回 -1
var name = 'Better';
console.log(name.indexOf('t')); // 2
console.log(name.indexOf('t', 3)); // 3
console.log(name.indexOf('Bet')); // 0
console.log(name.indexOf('BB')); // -1

// string.lastIndexOf(searchString, position),该办法和 indexOf 办法相似
// 这个办法是从字符串开端开始查找而不是从头开始查找
var name = 'Better';
console.log(name.lastIndexOf('t')); // 3
console.log(name.lastIndexOf('t', 2)); // 2
console.log(name.lastIndexOf('BB')); // -1

// string.localeCompare(that),该办法用于比拟两个字符串。console.log('a'.charCodeAt(0)); // 97
console.log('A'.charCodeAt(0)); // 65
console.log('a'.localeCompare('A')); // -1
console.log('A'.localeCompare('a')); // 1
console.log('a'.localeCompare('a')); // 0
console.log('aa'.localeCompare('a')); // 1

var m = ['AAA', 'A', 'aa', 'a', 'Aa', 'aaa'];
m.sort(function(a, b){return a.localeCompare(b);
});
console.log(m); // ["a", "A", "aa", "Aa", "aaa", "AAA"]

// string.match(regexp),如果没有 g 标识符,和应用 regexp.exec(string) 的后果雷同
// 如果 regexp 带有 g 标识符,那么它返回一个蕴含除捕捉分组之外的所有匹配数组
var text = '<html><body class="center"><p>' +
            'This is <b>bold</b>!</p></body></html>';
var tagsReg = /[^<>]+|<(\/?)([A-Za-z]+)([^<>]*)>/g;
var a, i;
a = text.match(tagsReg);
for(i = 0, len = a.length; i < len; i ++){console.log('[' + i + ']' + a[i]);
}
// 后果:// [0] <html>
// [1] <body class="center">
// [2] <p>
// [3] This is 
// [4] <b>
// [5] bold
// [6] </b>
// [7] !
// [8] </p>
// [9] </body>
// [10] </html>

// string.replace(searchValue, replaceValue)
// 该办法对 string 进行查找和替换操作,而后返回一个新的字符串。// searchValue 能够是字符串或者正则表达式,如果为字符串,只会替换第一个匹配
var string = 'fall_in_love_with';
console.log(string.replace('_', '-')); // fall-in_love_with

// 如果 searchValue 是一个正则表达式而且带有 g 标识符,那它将替换所有匹配
// 如果没有带 g 标识符,那么它仅替换第一个匹配的地位。var string = 'fall_in_love_with';
console.log(string.replace(/_/g, '-')); // fall-in-love-with
console.log(string.replace(/_/, '-')); // fall-in_love_with

var oldareacode = /\((\d{3})\)/g;
console.log('(555)666-1212'.replace(oldareacode, '$1-')); // 555-666-1212

// 如果 replaceValue 是一个函数,此办法将对每个匹配顺次调用,// 并且该函数返回的字符串被用作替换文本。传递给这个函数的第一个参数是整个被匹配的文本。// 第二个参数是分组 1 捕捉的文本,下一个参数是分组 2 捕捉的文本,顺次类推
String.prototype.entityify = (function(){
    var character = {
        '<': '&lt;',
        '>': '&gt;',
        '&': '&amp;',
        '"':'&quot;'
    };
    return function(){return this.replace(/[<>&"]/g, function(c){return character;});
    }
}()); // 这里应用立刻执行函数
console.log('<&>'.entityify()); // &lt;&amp;&gt;

// string.search(regexp),该办法和 indexOf 相似,// 区别是该办法只能承受一个正则表达式作为参数而不是字符串
var strSay = 'I fell in love with you at first sight !';
console.log(strSay.search(/love/)); // 10
console.log(strSay.search(/hate/)); // -1

// string.slice(start, end),截取字符串
var strSay = 'I fell in love with you at first sight !';
console.log(strSay.slice(2, 23)); // fell in love with you
console.log(strSay.slice(24)); // at first sigth
console.log(strSay.slice(-7)); // sigth !

// string.split(separator, limit),该办法把字符串宰割成一个字符串数组。// separator 参数能够是字符串也能够是正则表达式
// limit 参数可选,该参数用来限度被宰割的片段数量
var digits = '0123456789';
console.log(digits.split('')); // ["0","1","2","3","4","5","6","7","8","9"]
console.log(digits.split('', 6)); // ["0","1","2","3","4","5"]

var ip = '192.168.1.0';
var str = '|a|b|c|';
console.log(ip.split('.')); // ["192", "168", "1", "0"]
console.log(str.split('|')); // ["","a","b","c",""]

var text = 'first, middle  , last';
console.log(text.split(/\s*,\s*/)); // ["first", "middle", "last"]

// PS:来自分组捕捉的文本将会被蕴含在被宰割的数组中
var text = 'first, middle  , last';
console.log(text.split(/\s*(,)\s*/)); // ["first", ",", "middle", ",", "last"]

// string.substring(start, end),该办法和 slice 办法一样,只是它不能解决正数参数,咱们平时能够应用 slice 代替它

// string.toLocaleLowerCase() 和 string.toLowerCase(),把字符串的字母转换成小写
console.log('ABCabc'.toLocaleLowerCase()); // 'abcabc'
console.log('ABCabc'.toLowerCase()); // 'abcabc'

// string.toLocaleUpperCase() 和 string.toUpperCase(),把字符串的字母转换成大写
console.log('ABCabc'.toLocaleUpperCase()); // 'ABCABC'
console.log('ABCabc'.toUpperCase()); // 'ABCABC'

// String.fromCharCode(char...)
console.log(String.fromCharCode(67, 97, 116)); // 'Cat'

JSON

JavaScript 对象表示法(JavaScript Object Notation, 简称 JSON)是一种轻量级的数据交换格局。它基于 JavaScript 的对象字面量表示法。
JSON 对象是一个包容“名 / 值”对的无序汇合。名字能够是任何字符串。值能够是任何类型的 JSON 值。
JSON 数组是一个值的有序序列。其值能够是任何类型的 JSON 值,包含数组和对象。
JSON 字符串要被蕴含在一对双引号之间。

// 应用 JSON.stringify() 办法把对象或者数组转化为 JSON 字符串
var obj = {
    name: 'Better'    ,
    age: 24,
    boy: true,
    hobbyArr: ['movie', 'computer game'],
    obj1: {},
    func: function(){console.log(123);},
    null: null,
    undefined: undefined,
    weakness: undefined
};
var arrObj = [
    {
        name: 'Better',
        age: 24,
        boy: true,
        hobbyArr: ['movie', 'computer game'],
        obj1: {},
        func: function(){console.log(123);},
        null: null,
        undefined: undefined,
        weakness: undefined
    },
    {
        name: 'xiaoxin',
        age: 20,
        girl: true,
        hobbyArr: ['movie', 'computer game'],
        obj1: {},
        func: function(){return 123;},
        null: null,
        undefined: undefined,
        weakness: undefined
    }
];
console.log(JSON.stringify(obj));
// {
//   "name": "Better",
//   "age": 24,
//   "boy": true,
//   "hobbyArr": [
//     "movie",
//     "computer game"
//   ],
//   "obj1": {},
//   "null": null
// } 
console.log(JSON.stringify(arrObj));
// [
//   {
//     "name": "Better",
//     "age": 24,
//     "boy": true,
//     "hobbyArr": [
//       "movie",
//       "computer game"
//     ],
//     "obj1": {},
//     "null": null
//   },
//   {
//     "name": "xiaoxin",
//     "age": 20,
//     "girl": true,
//     "hobbyArr": [
//       "movie",
//       "computer game"
//     ],
//     "obj1": {},
//     "null": null
//   }
// ]
// 论断:JSON 会漠视掉值为函数和 undefined 的变量

// 应用 JSON.parse() 办法把 JSON 字符串转换成 JS 对象或数组
var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var jsonstr = '{"name":"Better","age": 24,"boy": true,"hobbyArr": ["movie","computer game"],"obj1": {},"null": null}';
console.log(JSON.parse(jsontext));
console.log(JSON.parse(jsonstr));

本文由 mdnice 多平台公布


  1. abc ↩
退出移动版