@GivenCui
        
        2017-02-08T10:10:09.000000Z
        字数 6862
        阅读 720
    慕课网 课程学习记录
原始类型: number, string, boolean, null, undefined
引用类型: Object (Function, Array, Date..)
弱类型的转换逻辑
var num = 32;num = "this is a string"; // 这在强类型语言是错误32 + 32 // 64 数字的加法运算"32" + 32 // 3232 字符串拼接"32" - 32 // 0 字符串转换成数字"32a" - 32 // NaN
1.数字和字符串之间的转换
/* 数字字符串相互转换, 与位置有关 *//* +号特殊,即是加法运算符,又是字符串连接符 */var x = 'this is string' + 88; // 'this is string88'var y = 88 + 'this is string'; // '88this is string'var z = 8 + 8 + 'test'; // '16test'/* 巧妙利用+/-隐式转换 */+'123' // 123+'123'+'123' // '123123' // 第二个+是字符串链接符+'abc' // NaN'123'-0 // 123'abc'-0 // NaN1234 + '' // '1234''' + 1234 // '1234'
2.对==,===的影响
'123' == 123 // true'123' === 123 // false0 == false // truenull == undefined // true// 判断null和undefined的方法null === null // trueundefined === undefined // true// NaN很特殊, 注意引用类型的比较{} == {} // false{} === {} // false[] == [] // false[] === [] // falseNaN == NaN // falseNaN === NaN // false
3.Boolean与Number 
(1) ==的情况
// 无论什么顺序, Boolean --> Number,而不是Number转Boolean// true -> 1; false -> 0true == 1 // truetrue == 2 // <=> 1==2 false1 == true // true2 == true // <=> 2==1 false
(2) 在条件语句中, 非0非空--> true
1?true:false // true'test'?true:false // true0?true:false // false''?true:false // false
string, boolean, number都有对应的包装对象 String, Boolean, Number
在JavaScript中只要引用了字符串(数字、布尔值也是一样的)的属性,JS就会将字符串通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个新创建的对象就会销毁(真实实现并不一定是这样,但整个过程看起来是这样)。这个过程就叫包装对象
var str = 'string';str.length // 6 调用了包装对象的属性lengthstr.t = 10; // 没有报错,说明属性赋值成功str.t // undefined, 说明包装对象已经销毁var num = 123;num.toFixed(2) // 123.00 调用了包装对象123.toFixed(2) // 报错
- typeof
 - instanceof
 - Object.prototype.toString.call/apply()
 - constructor
 - duck type (鸭子类型)
 
//----- 1. typeof -----// 用来判断基本类型和function, 除了nulltypeof 100 // "number"typeof NaN // "number"typeof true // "boolean"typeof function(){} // "function"typeof undefined // "undefined"typeof new Object() // "object"typeof [1,2] // "object"typeof null // "object", 历史遗留bug
//----- 2. instanceof -----// obj instanceof 构造函数// 基于原型链,适合自定义对象的检测// 不同windown和iframe会失效[] instanceof Array // true{} instanceof Object // truevar Person = function(){};var Student = function(){};Student.prototype = new Person();Student.prototype.constructor = Student; // 修正var p1 = new Person();var s1 = new Student();p1 instanceof Person; // truep1 instanceof Student; // falses1 instanceof Student; // true <=> s1.__proto__ === Student.prototypes1 instanceof Person; // true 原型链继承 <=> s1.__proto__.__proto__ === Person.prototype// 补充: 只有函数有prototype, 对象有__proto__(__proto__和constructor继承自Object.prototype)s1.hasOwnProperty("constructor"); // falseObject.prototype.hasOwnProperty("constructor"); // trueObject.prototype.hasOwnProperty("__proto__"); // true
//----- 3.Object.prototype.toString.apply -----Object.prototype.toString.apply([]); // "[object Array]"Object.prototype.toString.apply(function(){}); // "[object Function]"Object.prototype.toString.apply(null); // "[object Null]"Object.prototype.toString.apply(undefined); // "[object Undefined]"Object.prototype.toString.apply('123'); // "[object String]"Object.prototype.toString.apply(123); // "[object Number]"Object.prototype.toString.apply(true); // "[object Boolean]"

//----- 3.constructor -----// constructor是Object.prototype中的属性// 在构造函数被new调用(实例化)时,完成赋值: 构造函数.prototype.constructor = 构造函数// 所以 实例.constructor --> 构造函数Person.prototype.constructor === Person // truep1.constructor === Person // truePerson.prototype.hasOwnProperty('constructor') // truep1.hasOwnProperty('constructor') // false
//----- 4.duck type -----// argument类数组也可以用数组的功能(function () {var arr = Array.prototype.slice.apply(arguments);console.log(arr);})(1, 2, 3);//输出:[1, 2, 3]var arr = Array.prototype.slice.apply({ 0: 1, 1: 2, 2: 3, length: 3 });console.log(arr);//输出:[1, 2, 3]
总结 

/** param1 Array* param2 Array* return true or false*//*** string, boolean, number, undefined, null, function, data, global*/// 因为在node.js中运行, 所以window用global替代function arraysSimilar1(arr1, arr2) {// 判断是否参数为数组类型if (!(arr1 instanceof Array) || !(arr2 instanceof Array)) {return false;}// 判断长度if (arr1.length !== arr2.length) return false;var n = arr1.length,countMap1 = {},countMap2 = {},t1, t2,TYPES = ['string', 'boolean', 'number', 'undefined', 'null', 'function', 'date', 'global'];var typeOf = function (ele) {var r;if (ele === null) r = 'null';else if (ele instanceof Array) r = 'array';else if (ele === global) r = 'global';else if (ele instanceof Date) r = 'date';else r = typeof ele; // typeof 不能处理Object和nullreturn r;};for (var i = 0; i < n; i++) {t1 = typeOf(arr1[i]);t2 = typeOf(arr2[i]);if (countMap1[t1]) {countMap1[t1]++;} else {countMap1[t1] = 1;}if (countMap2[t2]) {countMap2[t2]++;} else {countMap2[t2] = 1;}}console.log(countMap1);console.log(countMap2);// 比较countMap1和countMap2对象是否一样for (i = 0, n = TYPES.length; i < n; i++) {if (countMap1[TYPES[i]] !== countMap2[TYPES[i]]) {return false;}}return true;}/* 方法二: */function arraysSimilar2(arr1, arr2) {if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length != arr2.length) {return false;}return typeOf(arr1) == typeOf(arr2);function typeOf(arr) {var types = [];for (var i in arr) {var ele = arr[i];if (ele === null) {types.push('null');} else if (ele instanceof Array) {types.push('array');} else if (ele === global) {types.push('global');} else if (ele instanceof Date) {types.push('date');} else {types.push(typeof(ele));}}return types.sort().toString();// return types.sort().join();}}// 测试数据var cases = [{arr1: [1, true, null],arr2: [null, false, 100],expect: true}, {arr1: [function() {}, 100],arr2: [100, {}],expect: false}, {arr1: [null, 999],arr2: [{}, 444],expect: false}, {arr1: [global, 1, true, new Date(), "hahaha", (function() {}), undefined],arr2: [undefined, (function() {}), "okokok", new Date(), false, 2, global],expect: true}, {arr1: [new Date()],arr2: [{}],expect: false}, {arr1: [global],arr2: [{}],expect: false}, {arr1: [undefined, 1],arr2: [null, 2],expect: false}, {arr1: [{}, {}, {}],arr2: [{}, {}, null],expect: false}, {arr1: null,arr2: null,expect: false}, {arr1: [],arr2: undefined,expect: false}, {arr1: "abc",arr2: "cba",expect: false}];// 测试函数var result = function(testObj) {//以下为多组测试数据// 验证for (var i = 0; i < cases.length; i++) {if (testObj(cases[i].arr1, cases[i].arr2) !== cases[i].expect) {console.log("不通过!case" + (i + 1) + "不正确!arr1=" + JSON.stringify(cases[i].arr1) + ", arr2=" + JSON.stringify(cases[i].arr2) + " 的判断结果不是" + cases[i].expect);console.log( "不通过");}}console.log( "通过");};result(arraysSimilar1);result(arraysSimilar2);









块语句 {} 表示, 没有块级作用域{1:1}; // 会报错, 解析成块语句var o = {1:1}; // 解析成字面量对象函数有作用域
var a = 1;var a=b=1; // => var a=1;b=1; b成了全局变量var a=1,b=1; // 正确写法// 验证var a = 'a',b = 'b',c = 'c';function test() {var a = b = 1;c = 1;}console.log(a); // 'a'console.log(b); // 'b'console.log(c); // 'c'test(); // 函数调用了才产生影响console.log(a); // 'a'console.log(b); // 1console.log(c); // 1
// 三种形式: try+catch; try+finally; try+catch+finally// 1. 简单try{throw "test";} catch(ex) {console.log(ex); // test} finally {console.log('finally');}// 结果:// "test"// "finally"// 2. 嵌套try{try{throw new Error("oops"); // 抛出异常}finally {console.log("finally");}} catch(ex){ // 接收来自里层的异常信息console.error("outer", ex.message);}// 结果:// "finally"// "outer"// 3. 嵌套// 错误被catch捕获就不会继续冒泡了try{try{throw new Error("oops");} catch (ex) {console.error("inner", ex.message);} finally {console.log("finally");}} catch (ex) {console.error("outer",ex.message);}// 结果:// "inner oops"// "finally"