@GivenCui
2017-02-08T18:10:09.000000Z
字数 6862
阅读 587
慕课网
课程学习记录
原始类型: 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 // NaN
1234 + '' // '1234'
'' + 1234 // '1234'
2.对==,===的影响
'123' == 123 // true
'123' === 123 // false
0 == false // true
null == undefined // true
// 判断null和undefined的方法
null === null // true
undefined === undefined // true
// NaN很特殊, 注意引用类型的比较
{} == {} // false
{} === {} // false
[] == [] // false
[] === [] // false
NaN == NaN // false
NaN === NaN // false
3.Boolean与Number
(1) ==的情况
// 无论什么顺序, Boolean --> Number,而不是Number转Boolean
// true -> 1; false -> 0
true == 1 // true
true == 2 // <=> 1==2 false
1 == true // true
2 == true // <=> 2==1 false
(2) 在条件语句中, 非0非空--> true
1?true:false // true
'test'?true:false // true
0?true:false // false
''?true:false // false
string, boolean, number都有对应的包装对象 String, Boolean, Number
在JavaScript中只要引用了字符串(数字、布尔值也是一样的)的属性,JS就会将字符串通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个新创建的对象就会销毁(真实实现并不一定是这样,但整个过程看起来是这样)。这个过程就叫包装对象
var str = 'string';
str.length // 6 调用了包装对象的属性length
str.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, 除了null
typeof 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 // true
var Person = function(){};
var Student = function(){};
Student.prototype = new Person();
Student.prototype.constructor = Student; // 修正
var p1 = new Person();
var s1 = new Student();
p1 instanceof Person; // true
p1 instanceof Student; // false
s1 instanceof Student; // true <=> s1.__proto__ === Student.prototype
s1 instanceof Person; // true 原型链继承 <=> s1.__proto__.__proto__ === Person.prototype
// 补充: 只有函数有prototype, 对象有__proto__(__proto__和constructor继承自Object.prototype)
s1.hasOwnProperty("constructor"); // false
Object.prototype.hasOwnProperty("constructor"); // true
Object.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 // true
p1.constructor === Person // true
Person.prototype.hasOwnProperty('constructor') // true
p1.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和null
return 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); // 1
console.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"