十一、强制转换html
强制转换主要指使用Number、String和Boolean三个构造函数,手动将各类类型的值,转换成数字、字符串或者布尔值。ajax
1>Number强制转换express
参数为原始类型值的转换规则:设计模式
Number(324) | 值:324 | 字符串若是能够被解析为数值,则转换为相应的数值 |
Number('324abc') | 值:NaN | 字符串:若是不能够被解析为数值,返回NaN |
Number('') | 值:0 | 空字符串转为0 |
Number(true) 、Number(false) | 值:一、0 | 布尔值:true 转成1,false 转成0 |
Number(undefined) | 值:NaN | undefined:转成 NaN |
Number(null) | 值:0 | null:转成0 |
Number函数将字符串转为数值,要比parseInt函数严格不少。基本上,只要有一个字符没法转成数值,整个字符串就会被转为NaN。
参数为对象的转换规则:简单的规则是,Number方法的参数是对象时,将返回NaN。数组
Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
实际上,Number背后的真正规则复杂得多,内部处理步骤以下:
1:调用对象自身的valueOf方法。若是返回原始类型的值,则直接对该值使用Number函数,再也不进行后续步骤。
2:若是valueOf方法返回的仍是对象,则改成调用对象自身的toString方法。若是返回原始类型的值,则对该值使用Number函数,再也不进行后续步骤。
3:若是toString方法返回的是对象,就报错。框架
2>String强制转换参数为原始类型值的转换规则:
数值:转为相应的字符串。
字符串:转换后仍是原来的值。
布尔值:true转为"true",false转为"false"。
undefined:转为"undefined"。
null:转为"null"。
参数为对象的转换规则:String方法的参数若是是对象,返回一个类型字符串;若是是数组,返回该数组的字符串形式。
String内部处理步骤以下:
1:先调用对象自身的toString方法。若是返回原始类型的值,则对该值使用String函数,再也不进行如下步骤。
2:若是toString方法返回的是对象,再调用valueOf方法。若是返回原始类型的值,则对该值使用String函数,再也不进行如下步骤。
3:若是valueOf方法返回的是对象,就报错异步
/* * 强制类型转换 * - 指将一个数据类型强制转换为其余的数据类型 * - 类型转换主要指,将其余的数据类型,转换为String 、Number 、Boolean * */
/* * 将其余的数据类型转换为String * 方式一: * - 调用被转换数据类型的toString()方法 * - 该方法不会影响到原变量,它会将转换的结果返回 * - 可是注意:null和undefined这两个值没有toString()方法,若是调用他们的方法,会报错 * * 方式二: * - 调用String()函数,并将被转换的数据做为参数传递给函数 * - 使用String()函数作强制类型转换时, * 对于Number和Boolean实际上就是调用的toString()方法 * 可是对于null和undefined,就不会调用toString()方法 * 它会将 null 直接转换为 "null" * 将 undefined 直接转换为 "undefined" * */
//1.调用被转换数据类型的toString()方法
var a = 123; a = a.toString(); console.log(typeof a); //string
a = true; a = a.toString(); console.log(typeof a); //string
a = null; a = a.toString(); console.log(typeof a); //报错,Uncaught TypeError: Cannot read property 'toString' of null
a = undefined; a = a.toString(); console.log(typeof a); //报错,Uncaught TypeError: Cannot read property 'toString' of undefined
//---------------------------------------------------------------------------------------------
//2.调用String()函数,并将被转换的数据做为参数传递给函数
a = 123; a = String(a); console.log(typeof a); //string
a = null; a = String(a); console.log(typeof a); //string
a = undefined; a = String(a); console.log(typeof a); //string
//3.我用Java中的方法,发现也是能够的
var b = 123; b = "" + b; console.log(typeof b); //string
3>Boolean强制转换ide
参数为原始类型值的转换规则:转换规则相对简单:除了如下六个值的转换结果为false,其余的值所有为true。
undefined、null、-0、0或+0、NaN、''(空字符串)
参数为对象的转换规则:全部对象(包括空对象)的转换结果都是true。 函数
(自动转换具备不肯定性,并且不易除错,建议在预期为布尔值、数值、字符串的地方,所有使用Boolean、Number和String函数进行显式转换。)post
自动转换的规则:预期什么类型的值,就调用该类型的转换函数。好比,某个位置预期为字符串,就调用String函数进行转换。若是该位置多是字符串,也多是数值,那么默认转为数值。
1:自动转换为布尔值:当JavaScript遇到预期为布尔值的地方(好比if语句的条件部分),就会将非布尔值的参数自动转换为布尔值。系统内部会自动调用Boolean函数。
if ( !undefined && !null && !0 && !NaN && !'' ) { console.log('true'); } // true
// 写法一 expression ? true : false
// 写法二 !! expression
2:自动转换为字符串:当JavaScript遇到预期为字符串的地方,就会将非字符串的数据自动转为字符串。系统内部会自动调用String函数。字符串的自动转换,主要发生在加法运算时。当一个值为字符串,另外一个值为非字符串,则后者转为字符串。(+号的拼接字符串的做用)
'5' + 1 // '51' | '5' + true // "5true" | '5' + false // "5false" | '5' + {} // "5[object Object]" |
'5' + [] // "5" | '5' + function (){} // "5function (){}" | '5' + undefined // "5undefined“ | '5' + null // "5null" |
3:自动转换为数值:当JavaScript遇到预期为数值的地方,就会将参数值自动转换为数值。系统内部会自动调用Number函数。
自动转换为数值举例 | |||
'5' - '2' =3 | '5' * '2'=10 | false - 1=-1 | true - 1= 0 |
'5' * [] = 0 | '1' - 1 = 0 | false / '5' = 0 | 'abc' - 1 = NaN |
4.除加法运算符有可能把运算子转为字符串,其余运算符都会把运算子自动转成数值。
+'abc' // NaN -'abc' // NaN +true // 1 -false // 0
特殊:(具体缘由经过度娘寻根问底)
null == undefined // true
null == false // false
undefined == false // false
var str; //undefined console.log("只定义未初始化的str类型"+typeof(str)+"只定义未初始化的str值"+str) var strone=""; //string console.log("初始化为\"\"的str类型"+typeof(strone)+"初始化为\"\"的str值"+strone) var strtwo=new String(); //无值至关于""; if(""==strtwo) console.log("初始化为new String()的str类型"+typeof(strtwo)+"初始化为new String()的str值"+strtwo) var strthree=null; //object console.log("初始化为null的str类型"+typeof(strthree)+"初始化为null的str值"+strthree) var strfour={}; //object console.log("初始化为{}的str类型"+typeof(strfour)+"初始化为{}的str值"+strfour)
1.顺序结构
2.选择结构
3.循环结构(当循环结构和直到型循环结构)
(一)选择语句
1)if语句
(1)单一选择结构:if(){}
var x=5,y=8; if(y>x) { alert("x>y");}
(2)二路选择结构:if(){}else{}
// 判断:若是第一个值大于第二个值则alert(OK!) var x=5,y=8; if(y> x){ document.write('OK!'); } else{ document.write('NOT OK!'); }
(3)三目运算符:?: (condition ? if_true : if_false;)
var x=5,y=8; alert(x> y? 'OK!' : 'NOT OK!')
(4)多路选择结构:if(){}else if(){}else if(){}else{}
多路选择结构流程图:
//此处给出主要代码为例 if(sScore >= 0 && sScore < 60) { alert('不及格,日常干啥啦!'); } else if(sScore >= 60 && sScore < 70) { alert('刚刚及格,继续努力!'); } else if(sScore >= 70 && sScore < 80) { alert('通常,再接再砺!'); } else if(sScore >= 80 && sScore < 90) { alert('良好,稳住,你能够的!'); } else if(sScore >= 90 && sScore < 100) { alert('优秀,戒骄戒躁,争取满分!'); } else if(sScore == 100) { alert('劳逸结合,注意身体!'); } else { alert('分数非法!'); }
2)switch语句(考虑多路选择的案例转换为switch实现,提示:case后的是具体的状况,多路选择是以表达式的方式进行判断,即点和面的关系。如:80-90范围这个面经过除以10,而后经过parseInt进行取整。(面转成点))
语法:switch(condition){case :break;default:}
break具体讲解:阻止代码向下一个case运行。防止case穿透(穿透性用的好仍是挺6的,有时间后续补充案例:给定依据具体日期得出这是本年的第多少天的案例)。
default具体讲解:匹配不存在时作的事情。
switch:严格检查类型(形似===的检查),若是不统一,条件不成立(好比说数字的字符串和case后的Number后的数字没法匹配,需转成相同的类型)
// 断定 switch(iWeekday){ //利用穿透性 case 0: case 7: alert('星期天'); break; case 1: alert('星期一'); break; case 2: alert('星期二'); break; case 3: alert('星期三'); break; case 4: alert('星期四'); break; case 5: alert('星期五'); break; case 6: alert('星期六'); break; default: alert('非法数据!'); }
(二)循环语句
1)for循环语句
// for循环语法 /* for(var i = 0; i < 10; i++){ code... } */ for(var a = 4; a < 10; a++) { document.write(a); } // for循环的嵌套 for(var i = 0; i < 5; i++) { for(var j = 0; j < 5; j++) { document.write(i*j + '、'); } document.write('<br>'); }
2)for in语句(能够遍历数组和对象,常常用于遍历对象)
遍历数组
var names = ["nick", "jenny"]; for(var index in names){ console.log(index); console.log(names[index]); }
遍历对象
var obj = {name: '张三', age: 24, hobby: ['打篮球', '搏击', '打乒乓球']}; for(var attr in obj) { console.log(obj[attr]); }
3)while循环语句
/* while语法 while(condition){ code... } */ var a = 4; while(a < 10) { document.write(a); a++; }
4)do-while语句
/* do...while语法 do{ code... }while(condition); */ var a = 4; do{ document.write(a); a++; } while(a < 10); // while和do...while的区别:执行的顺序不同 //do...while至少会执行一次代码块,while有可能一次都不执行。
(三)Label语句
//label语句 跳出双重循环 例:条件 i=5 j=5 时 跳出嵌套的双重for循环 num=55; var num = 0; outPoint: for (var i=0;i<10;i++) { for (var j=0;j<10;j++) { if (i==5 && j==5) { break outPoint; } num++; } } console.log(num); //控制台输出
(四)异常处理
try { //这段代码从上往下运行,其中任何一个语句抛出异常该代码块就结束运行 } catch (e) { // 若是try代码块中抛出了异常,catch代码块中的代码就会被执行。 //e是一个局部变量,用来指向Error对象或者其余抛出的对象 } finally { //不管上述代码怎么,finally代码块始终会执行 }
补充:break和continue的区别
// break和continue for(var i = 0; i < 10; i++) { if(i === 5) { break; } document.write(i); } for(var i = 0; i < 10; i++) { if(i === 5) { continue; } document.write(i); } // 区别:break终止循环,continue跳过当前循环。 // 共同点:都不会执行后面的代码
函数的概念:函数就是把完成特定功能的一段代码抽象出来,使之成为程序中的一个独立实体,起个名字(函数名)。能够在同一个程序或其余程序中屡次重复使用(经过函数名调用)。
注:编写好的函数代码只有经过调用才会执行,不调用的时候不会执行(自执行函数特例)。
函数的做用(好处):
1,使程序变得更简短而清晰
2,有利于程序维护
3,能够提升程序开发的效率 ,
4,提升了代码的重用性(复用性)
1>函数的建立方式
// 函数声明式的方式建立函数 function funcName() {} // 函数表达式的方式建立函数 var funcName = function () {}; // 经过构造函数的方式建立函数 // 构造函数:出如今new运算符后的函数,称为构造函数 var funcName = new Function ();
函数声明式和函数表达式的区别
// 函数声明式的方式必须指定函数名 function sum() { alert(1); } sum(); // 函数表达式的方式能够没有名字 (function () { alert(1); })();
2>函数的调用方式
//建立函数 function hello() { document.write('hello '); document.write('world '); } // 方式1:手动调用 hello(); // 方式2:事件驱动的方式 var oBox = document.getElementById('box'); oBox.onclick = function () { hello(); };
3>函数的参数(形参和实参)
1.手动传递的形参和实参
//函数定义时,定义的变量为形参:a,b function sum(a, b) { alert(a + b); }//函数调用时,传递的参数值为实参:4,8 sum(4, 8);
补充:对象中,冒号前面的数据能够称为键、下标、或者key,冒号后面的值称为值或者value
2.JS解析器内置定义的arguments (在函数内部的内置的对象参数,无需自定义可直接使用)
arguments 值类型(对象类型),包含的是实参的个数和数据
function sum(a, b) { // 经过下标的方式获取某一个值 console.log(arguments[0]); // 经过遍历的方式获取全部的值(下标0起始) for(var i = 0; i < arguments.length; i++) { console.log(arguments[i]); //分别控制台打印5,3,8 } a++; //a和arguments[0]和指向相同结果可想而知,相同为6 console.log(arguments[0]); //6 console.log(a); //6 } //手动调用函数 sum(5, 3, 8);
3.return(返回函数执行的结果)
// return关键词 function sum(a, b) { var c = a + b; return c;/*!return只能返回参数只能有一个。return a,b,c 最终返回的结果是c的结果,不会报错*/ /*!return 后面的代码不会执行*/ alert('hello world!');//永远不会被执行 // 函数默认返回的值是undefined } var d = sum(4, 7); console.log(d);
第一步:加载第一个script代码块
第二步:语法检查
第三步:预解析(将var声明的变量和声明式建立的函数放到代码的最前面)
第四步:开始正式执行代码,从上往下。
第五步:加载第二个script代码块。
sum(); var sum = function () { console.log(a + 8); } alert(a); //undefined alert(b); //报错 var a = 5; //代码预解析时,先将a和sum变量放到代码最前方,而后建立代码 var a,sum;而后自上而下执行代码 //预编译的代码结构: //var a,sum; //sum(); //var sum = function () { // console.log(a + 8); //} //alert(a); //undefined //alert(b); //报错 //a = 5;
由若干个键值对组成的无序集合。每一个属性存放一个原始值,对象或函数
属性:用属性值来描述他的状态
行为:用来改变队形的行为方法
1>对象申明
var obj = { name: 'jimmy', introduce: function () { console.log('我叫jimmy!'); } }; // 经过Object构造函数建立对象 // var obj = new Object(); // 经过自定义的构造函数建立对象 // function Animal() {} // var dog = new Animal(); // console.log(dog);
2>对象的操做
建立对象:
var bird = {feather: '羽毛', 'color': 'white', "type": '鸟类'}; var dog = {};
<1>对象调用
console.log(bird.feather);
console.log(bird["feather"]);
<2>对象增长
方式1:经过.的方式
dog.name = '旺财'; dog.wagTails = function () { console.log('旺财正在摇尾巴!'); }; // dog.wagTails();//调用
方式2:经过[]的方式
dog["name"] = '大黄'; dog['tongues'] = function () { alert('大黄正在吐舌头!'); } //dog.tongues(); //console.log(dog);
<3>对象修改
bird.feather = 'wing';
bird.color = 'pink';
<4>对象删除
delete bird.feather;
<5>对象清空
bird = {};
<6>对象销毁
// JS的垃圾回收机制:JS引擎检测内存,若是某个对象没有被变量引用,那么就会直接回收该对象 var obj = {size: 100000000}; obj = null;
//值类型(值相同,从新开辟内存空间) var a= 10; var b = a; a = 0; console.log(b);//10 //引用类型(地址相同,一块儿变) var a = {num: 10}; var b = a; a.num = 0; console.log(b.num);//0
var a = { name: '张三' }; var b = { name: a }; var c = b; var d = { name: '李四' }; c.name = d; console.log(b.name.name);//张三
1>回调函数(指针:经过函数名称的方式执行的函数)
回调函数就是一个经过函数指针调用的函数。若是你把函数的指针(地址)做为参数传递给另外一个函数,当这个指针被用为调用它所指向的函数时,咱们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。
所以,回调本质上是一种设计模式,而且jQuery(包括其余框架)的设计原则遵循了这个模式。
在JavaScript中,回调函数具体的定义为:函数A做为参数(函数引用)传递到另外一个函数B中,而且这个函数B执行函数A。咱们就说函数A叫作回调函数。若是没有名称(函数表达式),就叫作匿名回调函数。
所以callback 不必定用于异步,通常同步(阻塞)的场景下也常常用到回调,好比要求执行某些操做后执行回调函数。
例子
一个同步(阻塞)中使用回调的例子,目的是在func1代码执行完成后执行func2。
var func1=function(callback){ //do something. (callback && typeof(callback) === "function") && callback(); } func1(func2); var func2=function(){ }
function sum(a, b, fn) { var c = a + b; if(c > 9) { fn(); } console.log(c); } sum(7, 5, function () { alert(1); });
回调函数的使用场合
资源加载:动态加载js文件后执行回调,加载iframe后执行回调,ajax操做回调,图片加载完成执行回调,AJAX等等。
DOM事件及Node.js事件基于回调机制(Node.js回调可能会出现多层回调嵌套的问题)。
setTimeout的延迟时间为0,这个hack常常被用到,settimeout调用的函数其实就是一个callback的体现
链式调用:链式调用的时候,在赋值器(setter)方法中(或者自己没有返回值的方法中)很容易实现链式调用,而取值器(getter)相对来讲很差实现链式调用,由于你须要取值器返回你须要的数据而不是this指针,若是要实现链式方法,能够用回调函数来实现setTimeout、setInterval的函数调用获得其返回值。因为两个函数都是异步的,即:他们的调用时序和程序的主流程是相对独立的,因此没有办法在主体里面等待它们的返回值,它们被打开的时候程序也不会停下来等待,不然也就失去了setTimeout及setInterval的意义了,因此用return已经没有意义,只能使用callback。callback的意义在于将timer执行的结果通知给代理函数进行及时处理。
2>递归函数(自身调用自身的函数)
/* 递归函数调用分析: { var num = 1; num++; // 2 if(num < 5) { { var num = 2; num++; // 3 if(num < 5) { { var num = 3; num++; // 4 if(num < 5) { { var num = 4; num++; // 5 if(num < 5) { print(num); } console.log(num); // 5 } } console.log(num); } } console.log(num); } } console.log(num); } */ function print(num) { num++; if(num < 5) { print(num); } console.log(num); } print(1);
3>匿名函数
(function () {})();
4>构造函数
function Person() { alert(1); } var obj = new Person(); console.log(obj);
定义:数组是一个能够存储一组或一系列相关数据的容器。
为何要使用数组?
1:为了解决大量相关数据的存储和使用的问题。
2:模拟真实的世界(班级、军队)。
1>数组的操做
1)建立数组
(1)构造函数的方式:var a=new Array();
(2)隐式声明的方式:var b=[];
2)数组的赋值
构造函数函数的方式
(1)直接赋值:var a=new Array(数据1,数据2,…);
注:var a=new Array(数值) 若是括号中只有一个元素,而且这个元素是数值类型的,那么他就是指定数组的长度。 而且它的值都是undefined。
数组的属性:length 属性(获取整个数组的长度)。
(2)先声明后赋值:var a=new Array(); a[0]=1; a[1]=2; a[2]=3;
隐式声明赋值
(1)直接赋值: var a=[1,2,3,4];
(2)声明之后再赋值: var a=[]; a[0]=1; a[1]=2; a[2]=3;
注:JS数组能够存储任何类型的值。eg: arr[3] = function () {};
3)访问数组
经过数组的(中括号)下标访问。
arr[0-(length-1)] //数组下标从0开始,他的最大值,是length-1。
arr['name'] //关联数组 经过下表字符串进行访问
4) 修改数据:
arr[3] = '修改的数据';
5)删除数据:
delete arr[1];
6)遍历数组
1:for循环。
for(var i = 0; i < arr.length; i++) { console.log(arr[i]); }
2:while循环。
var i = 0; while(i < arr.length) { console.log(arr[i]); i++; }
3:for in循环。(遍历数组不经常使用)
数组的遍历。
for(var attr in arr){ //attr 数组的下标 console.log(arr[attr]) }
对象属性的遍历。
// 使用for in 遍历对象 var obj = {name: '小明', age: 24, hobby: ['打篮球', '搏击', '打乒乓球']}; for(var attr in obj) { console.log(obj[attr]); }
2>数组分类
1:按照下标的类型
1.下标是数字的类型叫作(索引数组)
var arr = ['1', '2' , '3'];
2.下标是字符串类型叫作(关联数组),必须经过对象模拟的形式才能实现,通常不用。
var arr = []; arr['name'] = '张三'; arr['age'] = '28';
3:按照维度来分类
1.一维数组经常使用的数组就是一维数组
2.二维数组,经过对象模拟的形式才能实现。
声明二维数组:
var arr=[[1,2,3],[4,5,6]]; alert(arr[1][1]); //值5
3>数组的属性
(1)length: 设置或返回数组元素的数目。(可读可写)
length属性控制数组的读:console.log(arr.length-1);
length属性控制数组的写:arr.length = 6;
(2)constructor:返回构造函数的引用。(输出constructor的返回值:Array)
4>数组的方法(加粗经常使用)
前五个对原始对象的操做
1. arr.push(数组元素1,数组元素2,........) 向数组的末尾加入新元素 | 返回值:新数组的长度
eg:arr.push('追加元素1','追加元素2');
2.arr.unshift(数组元素1,数组元素2,........) 向数组的开头加入新元素 | 返回值是新数组的长度。
eg:arr.unshift(开头新元素1,开头新元素2)
3. arr.pop() 删除数组的最后一个元素 | 返回值是删除的元素。
var first = arr.pop();
4. arr.shift() 删除数组的第一个元素 | 返回删除的元素。
var first = arr.shift();
5.万能的添加删除函数 arr.splice(index,数量,添加的元素.....) 注:前俩个元素必须有
(1)index 从何处开始添加或删除,必须是数值类型(数组的下标)
(2)数量 规定了删除的个数,若是是0,则不删除。
(3)须要添加的元素,能够看成替换的元素。
(4)若是有删除的元素,以数组的方式返回删除的元素。
// 添加元素 arr.splice(2, 0, '王五'); // 修改元素 arr.splice(1, 1, '王五'); //修改与添加 arr.splice(1, 1, '王五','李四'); // 删除元素 var del = arr.splice(1, 1);
6.arr.join([分隔符]) 把数组元素按照指定分隔符组合成一个字符串,若是没有指定分隔符,默认是用“,”分割 | 返回结果就是组合成的字符串。
var param = { q: '棉衣', commend: 'all', search_type: 'item' }; var aParam = []; for(var attr in param) { aParam.push(attr + '=' + param[attr]); } console.log(aParam.join('&')); //以字符&分割链接数组 //结果:q=棉衣&commend=all&search_type=item
7. arr.slice() 数组的分割。从截取指定的开始位置,到结束位置(不包括)的元素。若是不指定结束位置,则从指定的开始位置,取到结尾(数组的下标)。
支持负数(-1开头) 返回的是新数组。 不改动原来的数组。正数和负数都是向右查找
var arr = ['宋江', '卢俊义', '武松', '杨雄', '石秀', '鲁智深']; var newArr = arr.slice();至关于拷贝数组 var newArr = arr.slice(2);//不指定结束为止,默认为截取到最后 var newArr = arr.slice(2, 5);//结果为下标为二、三、4的数组元素,不包含为指定结尾下标数的元素 var newArr = arr.slice(-2, -1); //从末尾开始计数分割 只能按照从左向右的顺序进行截取,即不支持arr.slice(-1, -2) 结果:'石秀'
8. arr.concat() 链接两个或更多的数组,并返回新数组,对原数组没有任何影响。
eg:arr1.concat(arr2) //将数组arr1和arr2链接成新数组返回
9.arr.reverse() 数组翻转方法。改变原数组
arr.reverse(arr) //将数组翻转
10. arr.sort() 对数组进行排序,若是没有参数,则按照字母的编码进行排序,若是要按照其余的顺序来排序,要提供一个函数。
回调函数会提供两个参数(a,b)。
a<b a在b前。
a=b 顺序按照原样输出。
a>b b在a前。
['d', 'c', 'b', 'a'].sort() // ['a', 'b', 'c', 'd'] [4, 3, 2, 1].sort() // [1, 2, 3, 4] [11, 101].sort() // [101, 11] [10111, 1101, 111].sort() // [10111, 1101, 111]
若是想让sort方法按照自定义方式排序,能够传入一个函数做为参数,表示按照自定义方法进行排序。该函数自己接受两个参数,表示进行比较的两个元素。若是返回值大于0,表示第一个元素排在第二个元素后面;其余状况下,都是第一个元素排在第二个元素前面。
返回值正直交换 零、负值不交换 负值降序 正值升序
[10111, 1101, 111].sort(function (a, b) { return a - b; //回调函数 }) //输出结果: [111, 1101, 10111] [ { name: "张三", age: 30 }, { name: "李四", age: 24 }, { name: "王五", age: 28 } ].sort(function (o1, o2) { return o1.age - o2.age; }) // [ { name: "李四", age: 24 }, { name: "王五", age: 28 }, { name: "张三", age: 30 } ]
1>冒泡排序
// 冒泡排序:从前日后对相邻的两个数依次进行比较和调整,让较大的数往下沉,较小的往上冒 var arr = [23, 34, 11, 22, 19, 18]; /* 冒泡排序的思路分析: 第1轮 第1步:[23, 34, 11, 22, 19, 18] 第1轮 第2步:[23, 11, 34, 22, 19, 18] 第1轮 第3步:[23, 11, 22, 34, 19, 18] 第1轮 第4步:[23, 11, 22, 19, 34, 18] 第1轮 第5步:[23, 11, 22, 19, 18, 34] 第2轮 第1步:[11, 23, 22, 19, 18, 34] 第2轮 第2步:[11, 22, 23, 19, 18, 34] 第2轮 第3步:[11, 22, 19, 23, 18, 34] 第2轮 第4步:[11, 22, 19, 18, 23, 34] 第3轮 第1步:[11, 22, 19, 18, 23, 34] 第3轮 第2步:[11, 19, 22, 18, 23, 34] 第3轮 第3步:[11, 19, 18, 22, 23, 34] 第4轮 第1步:[11, 19, 18, 22, 23, 34] 第4轮 第2步:[11, 18, 19, 22, 23, 34] 第5轮 第1步:[11, 18, 19, 22, 23, 34] */
for(var i = 1; i < arr.length; i++) { // 内层for循环肯定每轮的步数 for(var j = 0; j < arr.length - i; j++) { // 两两比较 if(arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } }
2>选择排序
//选择排序:两两比较,找到最大值(或者最小值)以后,将其放在正确的位置,其余数的位置不变。 /* 选择排序的思路分析: 第1轮 第1步:var iMinK = 0; 第1轮 第2步:23 和 34比较,什么也不作 第1轮 第3步:23 和 11比较,iMinK = 2 第1轮 第4步:11 和 22比较,什么也不作 第1轮 第5步:11 和 19比较,什么也不作 第1轮 第6步:11 和 18比较,什么也不作 第1轮 第7步:下标0和下标2进行位置交换 [11, 34, 23, 22, 19, 18] 第2轮 第1步:var iMinK = 1; 第2轮 第2步:34 和 23比较,iMinK = 2 第2轮 第3步:23 和 22比较,iMinK = 3 第2轮 第4步:22 和 19比较,iMinK = 4 第2轮 第5步:19 和 18比较,iMinK = 5 第2轮 第6步:下标1和下标5进行位置交换 [11, 18, 23, 22, 19, 34] */
// 外层for循环肯定轮数 for(var i = 0; i < arr.length - 1; i++) { // 记录最小值的下标 var iMinK = i; for(var j = i + 1; j < arr.length; j++) { if(arr[iMinK] > arr[j]) { iMinK = j; } } // 交换数据 if(iMinK !== i) { var temp = arr[i]; arr[i] = arr[iMinK]; arr[iMinK] = temp; } }
3>插入排序
在要排序的一组数中,假设前面的数已是排好顺序的,如今要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。如此反复循环,直到所有排好顺序。
/* 插入排序的思路分析: 第1轮 第1步:[23, 34, 11, 22, 19, 18] 第2轮 第1步:[23, 11, 34, 22, 19, 18] 第2轮 第2步:[11, 23, 34, 22, 19, 18] 第3轮 第1步:[11, 23, 22, 34, 19, 18] 第3轮 第2步:[11, 22, 23, 34, 19, 18] 第3轮 第3步:[11, 22, 23, 34, 19, 18] 第4轮 第1步:[11, 22, 23, 19, 34, 18] 第4轮 第2步:[11, 22, 19, 23, 34, 18] 第4轮 第3步:[11, 19, 22, 23, 34, 18] 第4轮 第4步:[11, 19, 22, 23, 34, 18] 第5轮 第1步:[11, 19, 22, 23, 18, 34] 第5轮 第2步:[11, 19, 22, 18, 23, 34] 第5轮 第3步:[11, 19, 18, 22, 23, 34] 第5轮 第4步:[11, 18, 19, 22, 23, 34] 第5轮 第5步:[11, 18, 19, 22, 23, 34] */
for(var i = 1; i < arr.length; i++) { // 内层的for循环 for(var j = i; j > 0; j--) { if(arr[j] < arr[j - 1]) { var temp = arr[j]; arr[j] = arr[j - 1]; arr[j - 1] = temp; } else { break; } } }
4>快速排序
// 选择一个基准元素,一般选择第一个元素或者最后一个元素。 //经过一趟扫描,将待排序列分红两部分,一部分比基准元素小,一部分大于等于基准元素。 //此时基准元素在其排好序后的正确位置,而后在用一样的方法递归的排序划分的两部分。 /* 排序数组:23, 35, 34, 11, 22, 19, 18 快速排序的思路分析: 第一步:base = 23 , arr = [35, 34, 11, 22, 19, 18] 第二步:left = [], right = [] 第三步:[11, 22, 19, 18] 23 [35, 34] 第四步: [] 11 [22, 19, 18] 23 [34] 35 [] 第五步:[] 11 [19, 18] 22 [] 23 [34] 35 [] 第六步:[11, 18, 19, 22, 23, 34, 35] */ /* if(arr.length <= 1) { return arr; } var iBase = arr.shift(); var left = [], right = []; for(var i = 0; i < arr.length; i++) { if(arr[i] < iBase) { left.push(arr[i]); } else { right.push(arr[i]); } } left: [11, 22, 19, 18] iBase: 23 , right: [35, 34] 从上开始正推返回表达式:return quickSort(left即[11,22,19, 18]).concat(iBase=23, quickSort(right即[35,34])); 从下开始逆推返回值:return [11, 18, 19, 22].concat(23, [35,34]);//合并后的数组:[11,18,19,22,23,34,35] -------------------------------------------我是单次递归分割线----------------------------------------------- if(arr.length <= 1) { return arr; } var iBase = arr.shift(); var left = [], right = []; for(var i = 0; i < arr.length; i++) { if(arr[i] < iBase) { left.push(arr[i]); } else { right.push(arr[i]); } } left: [] iBase: 11 right: [22, 19, 18] 从上开始正推返回表达式:return quickSort(left即[]).concat(iBase=11, quickSort(right即[22,19,18])); 从下开始逆推返回值:return [].concat(11, [18, 19, 22]); //合并后的数组:[11, 18, 19, 22] -------------------------------------------我是单次递归分割线----------------------------------------------- if(arr.length <= 1) { return arr; } var iBase = arr.shift(); var left = [], right = []; for(var i = 0; i < arr.length; i++) { if(arr[i] < iBase) { left.push(arr[i]); } else { right.push(arr[i]); } } left: [19, 18] iBase: 22 right: [] 从上开始正推返回表达式:return quickSort(left即[19, 18]).concat(iBase=22, quickSort(right即[])); 从下开始逆推返回值:return [18, 19].concat(22, []); //合并后的数组: [18, 19, 22] -------------------------------------------我是单次递归分割线----------------------------------------------- if(arr.length <= 1) { return arr; } var iBase = arr.shift(); var left = [], right = []; for(var i = 0; i < arr.length; i++) { if(arr[i] < iBase) { left.push(arr[i]); } else { right.push(arr[i]); } } left: [18] iBase: 19, right: [] 从上开始正推返回表达式:return quickSort(left即[18]).concat(iBase=19, quickSort(right即[])); 从下开始逆推返回值:return [18].concat(19, []); //合并后的数组: [18, 19] */
var arr = [23, 35, 34, 11, 22, 19, 18, 18]; function quickSort(arr) { if(arr.length <= 1) { return arr; } var iBase = arr.shift(); var left = [], right = []; for(var i = 0; i < arr.length; i++) { if(arr[i] < iBase) { left.push(arr[i]); } else { right.push(arr[i]); } } return quickSort(left).concat(iBase, quickSort(right)); } var newArr = quickSort(arr); console.log(newArr);
进制间的转换(二进制、八进制、十进制、十六进制)
1>10进制转换为16进制:(10).tostring(16)
2>8转16:(012).tostring(16)
3>16转10:(0x).tostring(10)
4>10转2:(111111).tostring(2)
5>16转8:(0x16).tostring(8)
6>parseInt(10,2)
7>parseInt(12,16)
8>parseInt(12,8)
参数为原始类型值的转换规则:
原始类型的值主要是字符串、布尔值、undefined和null,它们都能被Number转成数值或NaN。
NaN:not a number,当数学计算得不到数字结果时,该值就是NaN(Number类型)。
isNaN:判断变量是否为NaN。
一、JavaScript 基础一 (从零学习JavaScript)
二、JavaScript 基础二 (从零学习JavaScript)
借鉴转载出处: http://www.cnblogs.com/witkeydu/