[关闭]
@GivenCui 2017-02-08T18:10:09.000000Z 字数 6862 阅读 587

JavaScript深入浅出

慕课网 课程学习记录


课程大纲

常用链接: https://developer.mozilla.org/zh-CN/learn/javascript

  1. 数据类型
  2. 表达式和运算符
  3. 语句
  4. 对象
  5. 数组
  6. 函数
  7. this
  8. 闭包和作用域
  9. OOP
  10. 正则与模式匹配

第一章 六种数据类型

原始类型: number, string, boolean, null, undefined
引用类型: Object (Function, Array, Date..)

弱类型特性

弱类型的转换逻辑

  1. var num = 32;
  2. num = "this is a string"; // 这在强类型语言是错误
  3. 32 + 32 // 64 数字的加法运算
  4. "32" + 32 // 3232 字符串拼接
  5. "32" - 32 // 0 字符串转换成数字
  6. "32a" - 32 // NaN

隐式转换

1.数字和字符串之间的转换

  1. /* 数字字符串相互转换, 与位置有关 */
  2. /* +号特殊,即是加法运算符,又是字符串连接符 */
  3. var x = 'this is string' + 88; // 'this is string88'
  4. var y = 88 + 'this is string'; // '88this is string'
  5. var z = 8 + 8 + 'test'; // '16test'
  6. /* 巧妙利用+/-隐式转换 */
  7. +'123' // 123
  8. +'123'+'123' // '123123' // 第二个+是字符串链接符
  9. +'abc' // NaN
  10. '123'-0 // 123
  11. 'abc'-0 // NaN
  12. 1234 + '' // '1234'
  13. '' + 1234 // '1234'

2.对==,===的影响

  1. '123' == 123 // true
  2. '123' === 123 // false
  3. 0 == false // true
  4. null == undefined // true
  5. // 判断null和undefined的方法
  6. null === null // true
  7. undefined === undefined // true
  8. // NaN很特殊, 注意引用类型的比较
  9. {} == {} // false
  10. {} === {} // false
  11. [] == [] // false
  12. [] === [] // false
  13. NaN == NaN // false
  14. NaN === NaN // false

3.Boolean与Number
(1) ==的情况

  1. // 无论什么顺序, Boolean --> Number,而不是Number转Boolean
  2. // true -> 1; false -> 0
  3. true == 1 // true
  4. true == 2 // <=> 1==2 false
  5. 1 == true // true
  6. 2 == true // <=> 2==1 false

(2) 在条件语句中, 非0非空--> true

  1. 1?true:false // true
  2. 'test'?true:false // true
  3. 0?true:false // false
  4. ''?true:false // false

包装对象

string, boolean, number都有对应的包装对象 String, Boolean, Number

在JavaScript中只要引用了字符串(数字、布尔值也是一样的)的属性,JS就会将字符串通过调用new String(s)的方式转换成对象,这个对象继承了字符串的方法,并被用来处理属性的引用。一旦属性引用结束,这个新创建的对象就会销毁(真实实现并不一定是这样,但整个过程看起来是这样)。这个过程就叫包装对象

  1. var str = 'string';
  2. str.length // 6 调用了包装对象的属性length
  3. str.t = 10; // 没有报错,说明属性赋值成功
  4. str.t // undefined, 说明包装对象已经销毁
  5. var num = 123;
  6. num.toFixed(2) // 123.00 调用了包装对象
  7. 123.toFixed(2) // 报错

5种类型检测

  1. typeof
  2. instanceof
  3. Object.prototype.toString.call/apply()
  4. constructor
  5. duck type (鸭子类型)
  1. //----- 1. typeof -----
  2. // 用来判断基本类型和function, 除了null
  3. typeof 100 // "number"
  4. typeof NaN // "number"
  5. typeof true // "boolean"
  6. typeof function(){} // "function"
  7. typeof undefined // "undefined"
  8. typeof new Object() // "object"
  9. typeof [1,2] // "object"
  10. typeof null // "object", 历史遗留bug
  1. //----- 2. instanceof -----
  2. // obj instanceof 构造函数
  3. // 基于原型链,适合自定义对象的检测
  4. // 不同windown和iframe会失效
  5. [] instanceof Array // true
  6. {} instanceof Object // true
  7. var Person = function(){};
  8. var Student = function(){};
  9. Student.prototype = new Person();
  10. Student.prototype.constructor = Student; // 修正
  11. var p1 = new Person();
  12. var s1 = new Student();
  13. p1 instanceof Person; // true
  14. p1 instanceof Student; // false
  15. s1 instanceof Student; // true <=> s1.__proto__ === Student.prototype
  16. s1 instanceof Person; // true 原型链继承 <=> s1.__proto__.__proto__ === Person.prototype
  17. // 补充: 只有函数有prototype, 对象有__proto__(__proto__和constructor继承自Object.prototype)
  18. s1.hasOwnProperty("constructor"); // false
  19. Object.prototype.hasOwnProperty("constructor"); // true
  20. Object.prototype.hasOwnProperty("__proto__"); // true
  1. //----- 3.Object.prototype.toString.apply -----
  2. Object.prototype.toString.apply([]); // "[object Array]"
  3. Object.prototype.toString.apply(function(){}); // "[object Function]"
  4. Object.prototype.toString.apply(null); // "[object Null]"
  5. Object.prototype.toString.apply(undefined); // "[object Undefined]"
  6. Object.prototype.toString.apply('123'); // "[object String]"
  7. Object.prototype.toString.apply(123); // "[object Number]"
  8. Object.prototype.toString.apply(true); // "[object Boolean]"

图片.png-12.9kB

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

总结
图片.png-61.4kB

1-6编程练习

拓展: in , Object.hasOwnPropertyNames(), Object.keys()的区别;

  1. /*
  2. * param1 Array
  3. * param2 Array
  4. * return true or false
  5. */
  6. /**
  7. * string, boolean, number, undefined, null, function, data, global
  8. */
  9. // 因为在node.js中运行, 所以window用global替代
  10. function arraysSimilar1(arr1, arr2) {
  11. // 判断是否参数为数组类型
  12. if (!(arr1 instanceof Array) || !(arr2 instanceof Array)) {
  13. return false;
  14. }
  15. // 判断长度
  16. if (arr1.length !== arr2.length) return false;
  17. var n = arr1.length,
  18. countMap1 = {},
  19. countMap2 = {},
  20. t1, t2,
  21. TYPES = ['string', 'boolean', 'number', 'undefined', 'null', 'function', 'date', 'global'];
  22. var typeOf = function (ele) {
  23. var r;
  24. if (ele === null) r = 'null';
  25. else if (ele instanceof Array) r = 'array';
  26. else if (ele === global) r = 'global';
  27. else if (ele instanceof Date) r = 'date';
  28. else r = typeof ele; // typeof 不能处理Object和null
  29. return r;
  30. };
  31. for (var i = 0; i < n; i++) {
  32. t1 = typeOf(arr1[i]);
  33. t2 = typeOf(arr2[i]);
  34. if (countMap1[t1]) {
  35. countMap1[t1]++;
  36. } else {
  37. countMap1[t1] = 1;
  38. }
  39. if (countMap2[t2]) {
  40. countMap2[t2]++;
  41. } else {
  42. countMap2[t2] = 1;
  43. }
  44. }
  45. console.log(countMap1);
  46. console.log(countMap2);
  47. // 比较countMap1和countMap2对象是否一样
  48. for (i = 0, n = TYPES.length; i < n; i++) {
  49. if (countMap1[TYPES[i]] !== countMap2[TYPES[i]]) {
  50. return false;
  51. }
  52. }
  53. return true;
  54. }
  55. /* 方法二: */
  56. function arraysSimilar2(arr1, arr2) {
  57. if (!Array.isArray(arr1) || !Array.isArray(arr2) || arr1.length != arr2.length) {
  58. return false;
  59. }
  60. return typeOf(arr1) == typeOf(arr2);
  61. function typeOf(arr) {
  62. var types = [];
  63. for (var i in arr) {
  64. var ele = arr[i];
  65. if (ele === null) {
  66. types.push('null');
  67. } else if (ele instanceof Array) {
  68. types.push('array');
  69. } else if (ele === global) {
  70. types.push('global');
  71. } else if (ele instanceof Date) {
  72. types.push('date');
  73. } else {
  74. types.push(typeof(ele));
  75. }
  76. }
  77. return types.sort().toString();
  78. // return types.sort().join();
  79. }
  80. }
  81. // 测试数据
  82. var cases = [{
  83. arr1: [1, true, null],
  84. arr2: [null, false, 100],
  85. expect: true
  86. }, {
  87. arr1: [function() {}, 100],
  88. arr2: [100, {}],
  89. expect: false
  90. }, {
  91. arr1: [null, 999],
  92. arr2: [{}, 444],
  93. expect: false
  94. }, {
  95. arr1: [global, 1, true, new Date(), "hahaha", (function() {}), undefined],
  96. arr2: [undefined, (function() {}), "okokok", new Date(), false, 2, global],
  97. expect: true
  98. }, {
  99. arr1: [new Date()],
  100. arr2: [{}],
  101. expect: false
  102. }, {
  103. arr1: [global],
  104. arr2: [{}],
  105. expect: false
  106. }, {
  107. arr1: [undefined, 1],
  108. arr2: [null, 2],
  109. expect: false
  110. }, {
  111. arr1: [{}, {}, {}],
  112. arr2: [{}, {}, null],
  113. expect: false
  114. }, {
  115. arr1: null,
  116. arr2: null,
  117. expect: false
  118. }, {
  119. arr1: [],
  120. arr2: undefined,
  121. expect: false
  122. }, {
  123. arr1: "abc",
  124. arr2: "cba",
  125. expect: false
  126. }];
  127. // 测试函数
  128. var result = function(testObj) {
  129. //以下为多组测试数据
  130. // 验证
  131. for (var i = 0; i < cases.length; i++) {
  132. if (testObj(cases[i].arr1, cases[i].arr2) !== cases[i].expect) {
  133. console.log("不通过!case" + (i + 1) + "不正确!arr1=" + JSON.stringify(cases[i].arr1) + ", arr2=" + JSON.stringify(cases[i].arr2) + " 的判断结果不是" + cases[i].expect);
  134. console.log( "不通过");
  135. }
  136. }
  137. console.log( "通过");
  138. };
  139. result(arraysSimilar1);
  140. result(arraysSimilar2);

第二章 表达式和运算符

表达式

图片.png-34.2kB

图片.png-32.2kB

图片.png-23.6kB

图片.png-50.4kB

图片.png-33.3kB

图片.png-18.4kB

图片.png-9.7kB

图片.png-21.2kB

运算符

图片.png-85.5kB

第三章 语句和严格模式

块语句

  1. 块语句 {} 表示, 没有块级作用域
  2. {1:1}; // 会报错, 解析成块语句
  3. var o = {1:1}; // 解析成字面量对象
  4. 函数有作用域

var

  1. var a = 1;
  2. var a=b=1; // => var a=1;b=1; b成了全局变量
  3. var a=1,b=1; // 正确写法
  4. // 验证
  5. var a = 'a',
  6. b = 'b',
  7. c = 'c';
  8. function test() {
  9. var a = b = 1;
  10. c = 1;
  11. }
  12. console.log(a); // 'a'
  13. console.log(b); // 'b'
  14. console.log(c); // 'c'
  15. test(); // 函数调用了才产生影响
  16. console.log(a); // 'a'
  17. console.log(b); // 1
  18. console.log(c); // 1

try/catch/finally语句

  1. // 三种形式: try+catch; try+finally; try+catch+finally
  2. // 1. 简单
  3. try{
  4. throw "test";
  5. } catch(ex) {
  6. console.log(ex); // test
  7. } finally {
  8. console.log('finally');
  9. }
  10. // 结果:
  11. // "test"
  12. // "finally"
  13. // 2. 嵌套
  14. try{
  15. try{
  16. throw new Error("oops"); // 抛出异常
  17. }
  18. finally {
  19. console.log("finally");
  20. }
  21. } catch(ex){ // 接收来自里层的异常信息
  22. console.error("outer", ex.message);
  23. }
  24. // 结果:
  25. // "finally"
  26. // "outer"
  27. // 3. 嵌套
  28. // 错误被catch捕获就不会继续冒泡了
  29. try{
  30. try{
  31. throw new Error("oops");
  32. } catch (ex) {
  33. console.error("inner", ex.message);
  34. } finally {
  35. console.log("finally");
  36. }
  37. } catch (ex) {
  38. console.error("outer",ex.message);
  39. }
  40. // 结果:
  41. // "inner oops"
  42. // "finally"
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注