js高级程序设计
defer 异步脚本,脚本延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。按顺序执行脚本。但在实际情况下,并不一定会按照顺序执行
最好只有一个延迟脚本。
支持H5的浏览器会忽略给脚本设置 defer 属性
async 异步脚本,不保证按脚本的先后顺序执行。
异步脚本一定会在页面的Load事件前执行。
IE10+支持严格模式
function test (){ a = 12; //没有var, a 是全局变量, 不推荐 严格模式下会报错 ”use strict" } test(); console.log(a); // 12 var num = 12; // 推荐加; if(a){ return true; // 推荐加{} }
5种基本数据类型 undefined null boolean number string
1种复杂数据类型 object array function这两个呢?
typeof undefined null
console.log(typeof null); // object console.log(typeof 333); // number function abc () { return 5; } console.log(typeof abc); // function // undefined var a; // 默认会有一个 undefined值 console.log(typeof a); // undefined console.log(typeof name); // undefiend 不定义也是 Undefiend var b = undefined console.log(b === undefined); // true console.log(typeof undefined); // undefined // null var a = null; // 空对象指针 console.log(typeof a); // object // 如果定义的变量b 准备用于保存对象,那么var b = null 感觉没啥用 var b = null b = {"name": 'kang123'} if (b) { // if(b!= null) console.log(b.name); } console.log(null === undefined); // false 类型不一致 console.log(null == undefined); // true undefined 值是派生null值的 ,ECMA-262 规定两者相等
返回false
var a = NaN if(a){ console.log('ok'); }else{ console.log('error'); // undefined null 0 false '' NaN }
NaN isNaN(a) 浮点数 Infinity无穷 8进制 16进制
var a = 1 var b = 01 // 8进制首位为 0 var bb = 080 // 无效8进制会忽略 0 解析为 80 var c = 0x1 // 16进制前两位为 0x console.log(a + bb + c); // 82 会转换为 10进制再相加 var d = 10.0 ; // 会解析为整数 10 // 浮点数最高17位,7位及以上小数 ECMAScript会转换为科学计数法 0.0000007 自动转换为 3e-7 // 0.1+0.2 != 0.3 // ECMAScript 基于IEEE754数值的浮点计算的通病 // ECMAScript 数值最大值,最小值,超出则是 Infinity 无穷 正负无穷 isFinite(a) // 判断 a 是否是有穷的。 console.log(Number.MAX_VALUE); console.log(Number.MIN_VALUE); // NaN 非数值,表示本来要返回数值的操作数未返回数值的情况, console.log(10/0); // Infinity console.log(NaN == NaN); // false NaN 与任何值都不相等,包括NaN本身 // isNaN(val) // 把 val 转换为数值,转换成功则返回 false console.log(isNaN("10")); // false 转换为10 console.log(isNaN(true)); // false 转换为1 console.log(isNaN(false)); // false 转换为0 console.log(isNaN('blue'));// true 转换不了 console.log(isNaN(NaN)); // true 转换不了
parseInt() toString()
数值转换 Number() // 复杂、少用 parseInt() parseFloat() // 字符串转数字,可传第二个参数10/8,指定转换为10进制,或者8进制 parseInt('10',2) // 2 转成二进制,'10'代表2 字符串转换 var a = 10; a.toString() // '10' a+'' // '10' null 和 undefined 没有toString() 可用 String(null)、String(undefined) 转换为 'null' 字符串 可传参数10/8,指定转换为10进制,或者8进制 var num = 10; num.toString(8) // 12
var a = 10+'5' // '105' break continue
var a = 10; b = '5'; console.log(a + b); // '105' // 两个值相加,如果有一个是字符串,拼接为字符串 var num = 0; for (var i = 1; i < 10; i++) { // 如果i = 0; i%5 = 0 就直接break 退出for循环,就不执行 num++, 此时 num = 0 ; if (i % 5 == 0) { break; } num++ } console.log(num); // 4 var num2 = 0; for (var i = 1; i < 10; i++) { if (i % 5 == 0) { continue; // 继续for循环,num++ 少执行一次 } num2++ } console.log(num2); // 8
函数参数 arguments 数组
function add2 () { if (arguments.length == 1) { // 函数的参数可由 arguments数组来获取,其长度由调用时传入的参数决定 return arguments[0] + 10 // arguments[0] 表示函数调用时传入的第一个值 } else if (arguments.length == 2) { return arguments[0] + arguments[1] } } console.log(add2(2)); console.log(add2(3, 4));
基本数据类型、引用数据类型、 栈内存、堆内存, 函数局部变量,垃圾回收机制
基本数据类型: undefined null boolean number string 栈内存 引用类型值 object 引用类型值可添加属性和方法, 引用类型值保存在堆内存中 var person = new Person(); person.name = 'kang' 基本数据类型:复制变量时,num1和num2都是5,独立存储,不受影响 var num1 = 5; var num2 = num1; 引用类型值:复制变量时, obj1和obj2都指向内存中的同一个对象,同时更新 var obj1 = new Object(); var obj2 = obj1; obj1.name='kang'; alert(obj2.name); // 'kang' ECMAScript 所有函数的参数都是按值传递(非引用传递,会同时更新)。 传递基本类型的值时,被传递的值会被复制给一个局部变量, arguments对象中的一个元素 person instanceof object // 判断是什么类型的对象 if 和 for 里面定义的变量会保存在全局环境中 if(true){ var color = 'blue' } alert(color);// blue for(var i = 0;i<10;i++){ // xxx } alert(i) // 10 javascript 自动垃圾回收、定时回收
对象字面量、数组字面量、函数传对象 数组 join() 转换为 字符串
//1. 对象 var obj = new Object() obj.name='kang'; //2. 对象字面量 常用 var person = { name:'xiaoming' } console.log(person.name); // xiaoming 推荐写法 console.log(person['name']); // 以数组形式,要传字符串 var key = 'name' console.log(person[key]); // 通过变量来访问属性 // 3.函数传对象 function test (arg) { if(typeof arg.name =='string'){ console.log(arg.name); } } test({ name:'kang' }) // 数组 var arr = new Array() arr[0] = 'a' console.log(arr); var arr2 = new Array(20) var arr3 = new Array('a','b','c') // 数组字面量表示法 var arr4 = [] var arr5 = ['a','b','c'] console.log(arr5); // ['a','b','c'] console.log(arr5.toString()); // 'a,b,c' console.log(arr5.toLocaleString()); console.log(arr5.valueOf()); // 返回数组['a','b','c'] //检测数组 // if(val instanceof Array){} // 项目中如果包括多个框架,则要用Array.isArray()来判断 // ES5 IE9+ // Array.isArray() // 更好 // 数组和对象都有 toString() toLocaleString() valueof() 方法 var arr7 = ['d','e','f'] console.log(arr7.toString()); // 'd,e,f' console.log(arr7.join('')); // 'def'
数组 shift() unshift() pop() push() 栈方法 队列方法 sort() concat() slice() splice()
// 数组栈方法 pop() push() 栈:后进先出,即最新添加的最早被删除,栈中数据的插入和删除发在生栈的顶部 // 数组队列方法 shift() unshift() 队列:先进后出 // 数组 排序 reverse() sort() 都不实用 function compare (a, b) { return a-b // return b-a 则是从大到小排序 } var arr = [3,6,8,22,10] console.log(arr.sort(compare)); // [3,6,8,10,22] 从小到大排序 // 数组合并 concat() var arr2 = ['2','3','4'] var arr3 = ['5','6','7'] var arr4 = arr2.concat(arr3) // ['2','3','4','5','6','7'] console.log(arr4); // 数组截取 slice() var arr7 = ['b','c','d','e','f'] console.log(arr7.slice(1, 4)); // ['c','d','e'] 项 console.log(arr7.slice(1)); // ['c','d','e','f'] 截到完 console.log(arr7.slice(-2, -1)); // 遇到负数则用数组长度加上参数值 即 slice(3,4) // ['e'] // 数组增删改 splice() 主要向数组中间插入值 // splice(index,num,newArr) //index 起始位置 Num 要删除的数量, newArr 新添加的 var arr8 = ['f','g','h','i','j'] // 删 var arr9 = arr8.splice(0,2) console.log(arr8); // 从0位开始,删掉2个 ['h','i','j'] console.log('arr9: ' + arr9); // 返回删除的值 ['g','h'] // 增 arr8.splice(2,0,'k','l','m') // 从第2位开始,删掉0个,添加3个 ['h','i','k','l','m','j'] // j 跑到最后了 console.log(arr8); // 改 arr8.splice(3,1,'w') // 从第3位开始,删除1个,添加1个,相当于修改,把'l'修改为'w' console.log(arr8);
es5 新增数组 some() every() filter() map() forEach() reduce() reduceRight() indexOf() lastIndexOf()
// es5 数组 indexOf(val,[index]) lastIndexOf(val,[index]) 找出下标,找不到返回 -1 var arr = ['a','b','c','d','e','b'] console.log(arr.indexOf('b')); // 1 console.log(arr.lastIndexOf('c')); // 2 console.log(arr.indexOf('b', 2)); //5 要查找的项 b 以及开始查找的索引 2 // /* es5 数组 * every(function(item,index,arr){}) 数组的值,索引、数组本身 每一项都返回true ,结果返回 true * some() 有一项返回 true,结果返回 true * filter() // 返回符合条件的数组 * map() // 对数组每一项进行 for循环 返回处理过的数组 * forEach() // for循环,没有返回值 * */ // every() var arr= [3,4,5,6,7] var res = arr.every(function (item, index, arr) { // arr.some() 则返回 true return item > 4 // 数组所有项要大于4 }) console.log(res); // false /* es5 数组 * reduce(function(prev,cur,index,arr)) * for循环数组,prev 上一个值 cur当前值,index索引,arr数组本身,返回结果会赋值到 prev 从左到右执行 * reduceRight() 从右到左 * * */ var nums = [3,4,5,6,7] var num = nums.reduce(function (prev, cur, index, arr) { return prev+cur }) console.log(num) // 25 第一次迭代,prev = 3,cur = 4, 结果为7 ,第二次 prev= 7,cur=5,结果为12,在第三次prev = 12..
date() 获得毫秒数 +new Date() / new Date.getTime() / new Date.valueOf() / es5 添加 Date.now() toString() toLocaleString() 不同环境(浏览器/ nodejs)返回不一样
/* Date() * Date.parse(str) 返回指定日期,参数是美国格式的日期字符串 May 5,2014等 * Date.UTC(year,month,date,hours,minute,second) 返回指定日期 year 和 month 是必传参数,其他可省略 * * */ console.log(new Date()) // Sat Jul 15 2017 16:44:11 GMT+0800 (中国标准时间) console.log(new Date(Date.parse('May 5,2014'))); console.log(new Date('May 5,2014')); // 结果跟上一样,返回指定日期 console.log(new Date(Date.UTC(2005, 5))); // 基于GMT 返回指定日期 console.log(new Date(2005, 5)); // 基于本地时区 /** +new Date() 、 new Date().getTime() 、 new Date().valueOf() 返回当前毫秒数, * es5 添加 Data.now() 返回当前毫秒数, */ console.log(Date.now()); // 150010810002 console.log(+new Date()); // 150010810003 console.log(new Date().getTime()); // 150010810004 console.log(new Date().valueOf()); // 150010810005 /* // 取得当前时间 var start = Date.now() // 调用某函数 doSomething() // 取得结束时间 var end = Date.now() result = end - start */ // Date // toLocalString() toString() 代码调试用 不同环境、不同浏览器返回结果不一样 // var data1 = new Date(2017,1,1) var data2 = new Date(2017,2,1) console.log(data1 > data2); // false console.log(new Date(2017, 3, 1).toString()); // Sat Apr 01 2017 00:00:00 GMT+0800 (中国标准时间) console.log(new Date().toLocaleString()); // "2017/7/15 下午4:27:40" nodejs 环境返回不一样
正则 new RegExp() exec()
var reg = /a\.b/g console.log(reg.test('a.bc')); var reg2 = new RegExp("a\.b",'g') // 参数是字符串 console.log(reg2.test('a.bc')); var reg3 = /a\.b/g console.log(reg3.exec('a.bc')); // ['a.b' index:0, input: 'a.bc']
函数声明、 函数表达式 var test = function(){} 函数名本身是一个变量, 那么,函数参数可以是一个函数,函数返回值也可以是一个函数, 函数递归
arguments.callee arguments.callee.caller
/* function var sum = new Function('a','b','return a+b'); //不推荐 会解析两次代码,影响性能 函数名实际上也是一个指向函数对象的指针 函数没有重载的概念,同名函数,后定义的会覆盖先定义的 * */ console.log(test(1, 2)); function test (a, b) { // 函数声明 JS解析器会率先读取函数声明,并使其在执行任何代码(调用)之前可用,所以,先调用函数也可以正确执行 return a+b; } // console.log(num(1, 2)); // 报错,未定义 num函数 var num = function (a, b) { // 函数表达式 JS解析器按顺序执行, return a+b; } /* 函数名本身是一个变量 ,函数参数可以是一个函数 */ function test2 (fn, val) { return fn(val) } function add (val) { return val + 10 } console.log(test2(add, 20)); /* 函数名本身是一个变量 ,函数返回值可以是一个函数 */ /* 函数的 arguments数组存储函数的变量,有一个参数 callee指向拥有 arguments的函数 }*/ function calc (num) { if(num<=1){ return 1; }else{ return num*calc(num - 1) // 返回一个函数 递归 } } console.log(calc(5)); // 120 function calc2 (num) { // 'use strict' 严格模式下 arguments.callee() 会报错 if(num<=1){ return 1 }else{ return num*arguments.callee(num-1) // 使用 arguments.callee 代替 calc2 防止函数被改写后,受影响 } } console.log(calc2(6)); // 720 var cal3 = calc2 console.log(cal3(4)); // 24 calc2 = function () { return 0 } console.log(cal3(4)); // 24 上面的calc2 被改写了, 如果没有 arguements.callee代替 calc2 ,则会返回 0 console.log(calc2(3)); // 函数被重新处理为 0 function outer () { inner(); } function inner () { console.log(arguments.callee.caller); // caller可以 获取调用本函数 inner()的函数 } outer(); // 输出 outer()函数的内容 function outer () {inner();}
函数 length属性、prototype属性 apply() call() es5添加 bind() 改变this作用域
/* 函数是对象,函数也有属性和方法,每个函数都有属性length和prototype * length 是函数参数的个数 * */ function test10 (a, b) { return a+b; } console.log(test10.length); // 2 2个参数返回2 /* * ECMAScript 所有方法都保存在 prototype属性中,通过各自实例来调用 toString() valueOf()等 * es5 prototype不可枚举,不可for...in 输出 * 每个函数都有 apply() /call() * * */ function sum (a,b) { return a+b; } function callSum () { return sum.apply(this,arguments) // 传入this, 第二个参数 为 arguments 或参数数组 [a,b] } console.log(callSum(3,4)); function call2Sum () { return sum.call(this,a,b) // 传入this ,以及每一个参数 } /* call() apply 改变函数this 的作用域*/ window.color ='red' var o = {color:'blue'} function say () { console.log(this.color); } say.call(this) // red 全局环境下,this指向 window say.call(window) // red say.call(o) // blue this指向了对象 o , say.apply(o) // blue apply和call作用一样 /* es5 新增 bind() 改变函数this的作用域*/ var newSay = say.bind(o) // bind()创建了函数实例, newSay(); // blue 这里要调一下函数
Boolean Number String 不推荐使用 toFix(2) 四舍五入为字符串
/* ECMAScript 提供3个特殊的引用类型(基本包装类型) Boolean Number String 来处理基本类型值,内存中自动处理,不推荐手动调用 */ var s1 = 'abc'; var s2 = s1.substr(2) /* 内存执行过程, 先创建实例,执行完后,再销毁 * var s1 = new String('abc'); * var s2 = s1.substring(2) * s1 = null; * */ var s3 = 'cde' s3.color='blue' // 内存中 var s3 = new String('cde'); s3.color='blue',执行后,s3=null,马上清空, 再执行下一行时,color属性没了 console.log(s3.color); // undefined 执行上一行后,s3被清空了 var obj = new Object('abc') console.log(obj instanceof String); // true var val = 23; var number = Number(val) console.log(typeof number); var num2 = new Number(val); // 实例化一个对象 不建议 console.log(typeof num2); // object // 布尔表达式中的对象都会转换为 true var obj = new Boolean(false) // 不建议用 Boolean console.log(obj && true); // true // Number toFix() 自动四舍五入为字符串 toPrecision()不常用 toExponential() 转换为科学计数法 不常用 var num = 10.005; console.log(typeof num.toString()); // '10.005' console.log(typeof num.toFixed(2)); // '10.01'
字符串常用方法 chatAt() concat() slice() substring() substr() indexOf() lastIndexOf() es5新增 trim() match() search() split() localeCompare()
/* 字符串操作 chatAt*/ var str1 = 'abcde' console.log(str1.charAt(2)); // 'c' console.log(str1[3]); // 'd' 字符串数组写法 /* concat 合并 数组也有 */ var str2 = 'dd' var str3 = 'ee' console.log(str2.concat(str3)); console.log(str2 + str3); // 直接用 + 解决 /* slice(a,b) substring(a,b) 字符串截取两个索引值 数组也有 slice() substr(a,length) 一个索引值,一个字符串长度 */ var str4 = 'abcdefg' console.log(str4.slice(2, 3)); // c console.log(str4.substring(2, 3)); // c console.log(str4.substr(2, 3)); // cde /* 负数情况 */ /* slice() 会把传入的负值与字符串的长度相加 * substring() 将所有的负值参数都转换为0 * substr() 将负的第一个参数加上字符串的长度,将负的第二个参数转换为0 * */ console.log(str4.slice(2, -3)); // slice(2,7-3)= slice(2,4) = > 'cd' console.log(str4.substring(2, -3)); // substring(2,0) = substring(0,2) => 'ab' console.log(str4.substr(-2, -3)); // '' /* indexOf lastIndexOf*/ var str5 = 'wpsabcps' // es5数组也有 indexOf console.log(str5.indexOf('p')); // 1 console.log(str5.indexOf('p',2)); // 6 从第二个位置找p /* es5 添加 trim() 去除前后空格 */ var str6 = ' xxx aaa '; console.log(str6.trim()); // 返回新的字符串 /* 字符串匹配 match 与 reg.exec('str') 结果相同,返回数组,顺序反了 */ var str7 = 'wpsddd' var reg = /d/ console.log(str7.match(reg)); // ['d' ,index:3 ,input: 'wpsddd'] /* search() 返回索引 ,找不到返回 -1 */ var str8 = 'windows' var reg2 = /dow/; console.log(str8.search(reg2)); // 3 /* replace(a,b) 把 a 替换为b */ var str9 = 'mayun' console.log(str9.replace('a', 'b')); // mbyun 其他复杂方法见电子书 /* split 把字符串切割为数组 数组转换字符串用 join() */ var str10 = 'blue,mark,test' console.log(str10.split(',')); // ['blue','mark','test'] console.log(str10.split(',',2)); // ['blue','mark'] 第二个参数为返回数组的长度 /* 字符串比较 localeCompare 跟地区有关 */ var str11 = 'test' console.log(str11.localeCompare('yellow')); // -1 按顺序 t在 y 后面 ? false console.log(str11.localeCompare('banner')); // 1 按顺序 t在 b 后面 ? yes
url编码 encodeURIComponent() 编码 decodeURIComponent() 解码 eval() Math.max() 求数组最大值 Math.max.apply(Math, arr)
/* url 编码 * encodeURI() 只编码空格 * encodeURIComponent() 常用,把非数字字母进行编码 * */ var url = 'www.baidu.com?page=1' console.log(encodeURIComponent(url)); // www.baidu.com%3Fpage%3D1 /* url 解码 * decodeURI() * decodeURIComponent() * */ /* * eval(js) * 把传入的字符串当成js来解析 * * */ eval("console.log('abc')") // 'abc' eval("var num = 12") // 这里定义了 Num console.log(num) // 12 /* es5 禁止给 undefined NaN Infinity 赋值 */ // Math.max() Math.min() Math.floor() Math.ceil() Math.random() console.log(Math.max(3, 5, 6, 8)); // 8 这里是用括号 // 求数组最大值 var arr = [3,5,6,8] console.log(Math.max.apply(Math, arr)); // 8 apply() 指定this的作用域为 Math对象,第二个传入一个数组

浙公网安备 33010602011771号