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 规定两者相等
View Code

  返回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  转换不了
View Code

 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 
View Code

 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
View Code

 函数参数  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  //  判断是什么类型的对象  

iffor 里面定义的变量会保存在全局环境中
if(true){
    var color = 'blue'
}
alert(color);// blue   

for(var i = 0;i<10;i++){
//    xxx
}
alert(i)  // 10  

javascript 自动垃圾回收、定时回收
View Code

 对象字面量、数组字面量、函数传对象   数组 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'
View Code

 数组 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);
View Code

 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..
View Code

 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 环境返回不一样
View Code

 正则  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();}
View Code

 函数 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  这里要调一下函数
View Code

 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'
View Code

 字符串常用方法 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对象,第二个传入一个数组
View Code

 

posted @ 2017-07-08 16:12  gyz418  阅读(224)  评论(0)    收藏  举报