js高级程序设计

时间:2021-06-17 15:27:07

defer 异步脚本,脚本延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。按顺序执行脚本。但在实际情况下,并不一定会按照顺序执行
最好只有一个延迟脚本。
支持H5的浏览器会忽略给脚本设置 defer 属性
async 异步脚本,不保证按脚本的先后顺序执行。
异步脚本一定会在页面的Load事件前执行。

IE10+支持严格模式

function test (){
a = 12; //没有var, a 是全局变量, 不推荐 严格模式下会报错 ”use strict"
}
test();
console.log(a); // 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); // var num2 = 0;
for (var i = 1; i < 10; i++) {
if (i % 5 == 0) {
continue; // 继续for循环,num++ 少执行一次
}
num2++
}
console.log(num2); //

函数参数  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')); //
console.log(arr.lastIndexOf('c')); //
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()); //
console.log(+new Date()); //
console.log(new Date().getTime()); //
console.log(new Date().valueOf()); // /*
// 取得当前时间
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)); // 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)); // var cal3 = calc2
console.log(cal3(4)); //
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')); //
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)); //
/* 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) //
/* 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对象,第二个传入一个数组