前言
数据类型(type):能够表示并操作的值的类型
变量(variable):一个值的符号名称,可以通过名称获得对值的引用
弱类型特性:
var num=32;
num="this is a string";
32+32 //64
"32"+32 //"3232"
"32"-32 //0
js的数据类型:
原始类型(primitive type):数字、字符串和布尔值;null(空)和undfined(未定义)
对象类型(object type):对象(object)是属性(property)的集合。属性:名/值(值可以是:数字、字符串、对象)
(1)普通对象:“命名值”无序集合
(2)数组(array):带编号的值的有序集合
(3)函数(function):具有与它相关联的可执行的对象,通过调用函数运行可执行代码。
(4)日期(Date)
可变类型(mutable):数字、字符串、布尔值、null、undefined、
不可变类型(immutable):对象、数组
js的变量是无类型(untyped),变量可以被赋予任何类型的值
数字
js不区分整数值和浮点数值
1.整型直接量。识别十进制、十六进制,禁止十八进制。
2.浮点型直接量。
算术运算Math对象
+ - * / % //基本运算
//复杂运算
Math.random() //随机数
Math.pow(2,5) //2的5次幂
Math.round(.6) //四舍五入
Math.ceil(.6) //向上取整
Math.floor(.6) //向下取整
Math.abs(-5) //求绝对值
Math.max(x,y,z) //取最大
Math.min(x,y,z) //取最小
Math.E //自然对数的底数
Math.PI //π
Math.sqrt(3) //3的平方根
Math.pow(3,1/3) //3的立方根
Math.sin(0) //三角函数
Math.log(10) //10的自然对数
Math.log(100)/Math.LN10 //以10为低100的对数
Math.exp(3) //e的三次幂
溢出、下溢、被零整除不报错
Infinity //溢出
-Infinity
0 //下溢
负0
NaN //非数字(0/0)
二进制浮点数和四舍五入错误
通过浮点数的形式只能表示其中有限的个数,是近似值
var x=.3-.2;
var y=.2-.1;
x==y //false,不相等!!!
x==.1 //false
y==.1 //true
日期和时间
var then=new Date(2017,5,28); //2017年6月28日
var later=new Date(2017,5,28,21,10,25);//2017年6月28日21时10分25秒
var now =new Date(); //获取当前日期和时间
var elapsed=now-later; //时间间隔
later.getFullYear();
later.getMonth() //从0开始计数的月份
later.getDate() //天数,从1开始计数的天数
later.getDay() //星期 0代表星期日,5代表星期一
later.getHours()
later.getUTCHours() //UTC表示小时的时间,基于时区
/*计时器小程序*/
<body onload="time()">
<script >
function time(){
var date=new Date();
var h=date.getHours();
var m=date.getMinutes();
var s=date.getSeconds();
m=countTime(m);
s=countTime(s);
document.getElementById("timetxt").innerHTML=h+":"+m+":"+s;
t=setTimeout(function () {
time();
},500);
}
function countTime(i){
if(i<10){
i="0"+i;
}
return i;
}
</script>
<div id="timetxt"></div>
</body>
文本
1.字符串直接量
""
'testing'
"3.14"
"Hello 'World'!"
js和html一起使用时,最好用各自独立的引号风格
<button onclick="alert('Click Me')">Click Me</button>
2.转义字符
\o //NUL字符
\b //退格
\t //水平制表
\n //换行
\v //垂直制表
\f //换页
\r //回车
\" //双引号
\' //单引号
\\ //反斜杠
\xXX //两位十六进制XX指定的Latin-1字符
\uXXXX //四位十六进制XXXX指定的Unicode字符
3.字符串的使用
(1)字符串连接
msg="Hello,"+"world";
greeting="Hello,"+" "+name;
(2)字符串的属性
var s="hello,World" //定义一个字符串
s.charAt(0) //取第一个字符“h”
s.chatAt(s.length-1) //取最后一个字符“d”
s.substring(1,4) //取2~4的字符“ell”,
s.slice(1,4) //同上
s.slice(-3) //取最后三个字符“rld”
s.indexOf("1") //字符“1”首次出现的位置,找不到则返回-1
s.indexOf("1",3) //位置3及以后首次出现“1”的位置
s.lastIndexOf("1") //字符“1”出现最后一次的位置
s.split(",") //以“,”分割字符串为数组 “hello” “world”
s.replace("h","H") //全文“H”代替“h”
s.toUpperCase() //变大写
s.toLowerCase() //变小写
s.match("world");//内容匹配到返回字符串,否则返回null
Array数组对象
常用方法:
join():将所有元素转化为字符串并连接
是String.split()的逆向操作
var a=[1,2,3];
a.join(); //返回"1,2,3"
b.join("—"); //"1_2_3"
a.join(" "); //返回"1 2 3"
a.join(""); //返回"123"
var b=new Array(10);
b.join("-"); //'---------'
concat():合并,原数组未改变
var a=["hello" ,"world"];
var b=["Hello" ,"World"];
var c=a.concat(b);
splice():在数组中插入或者删除元素,原数组被修改
var a=[1,2,3,4,5,6,7,8];
a.splice(4);//一个参数,删除的起始位置。返回[5,6,7,8]
a.splice(1,2);//两个参数,前者是起始位置,后者是删除个数。返回[2,3]
sort():排序,转换为字符串再排序,原数组改变
var b=["z" ,"f"];
//顺序
document.write(b.sort());
//如果想按数字大小排顺序,添加一个比较函数
document.write(b.sort(function(a,b){
return a-b;
});
//按数字大小排倒序
document.write(b.sort(function(a,b){
return b-a;
});
push():在数组的尾部追加,进栈
pop():在数组的尾部删除,出栈
返回数组长度,修改替换原数组而非生成修改版的新数组
var stack=[];
stack.push(1,2);//stack:[1,2] 返回2
stack.pop();//stack:[1] 返回2,因为原数组长度是2
unshift():在数组的头部插入,返回新数组长度
shift():在数组的头部删除,返回删除元素
var a=[1];
a.unshift(2); //a:[2,1] 返回2
a.shift(); //a:[1] 返回2
reverse():翻转,会影响原数组
var a=["hello" ,"world"];
a.reverse();
document.write(a); //"world","hello"
slice():指定数组的片段或子数组,不改变原数组
var a=[1,2,3,4,5];
a.slice(1,-1); //第2~倒数第2的片段,返回[2,3,4]
toString():将每个元素转为字符串
toLocaleString():本地化版本
[1,2,3].toString();//返回'1,2,3'
["a","b","c"]toString();//返回'a,b,c'
ECMAScript5定义的新数组方法:
大多数调用三个参数:数组元素,元素索引,数组本身
ECMAScript5定义的新数组方法不会修改原始数组
forEach():数组遍历
不会有break语句式遍历提前终止,但可以抛出foreach.break异常来终止
var data=[1,2,3,4,5];
/*一个参数*/
var sum =0;
data.forEach(
function(value){
sum+=value;
}
);
sum;//为15
/*多个参数,第二、三参数可选,调用的函数看作是后两个参数的方法,作为this关键字来使用*/
data.forEach(
function(v,i,a){
a[i]=v+1;
}
);
data;//为[2,3,4,5,6]
//抛出foreach.break异常来终止遍历
function foreach(a,f,t){
try{
a.forEach(f,t);
}catch(e){
if(e===foreach.break){
return;
}else{
throw e;
}
}
}
foreach.break=new Error("StopIteration");
map():数组映射。将每个元素传递给指定函数,返回一个数组,包含函数的返回值,原数组未修改
a=[1,2,3];
b=a.map(
function(x){
return x*x;
}
);
b;//b是[1,4,9]
filter():数组过滤。调用数组的一个子集。传递函数是逻辑判断的,true则返回true或能转化为true的值
a=[5,4,3,2,1];
//一个参数
samllvalues=a.filter(
function(x){
return x<3;
}
);//返回[2,1]
//两个参数
evennumber=a.filter(
function(x,i){
return i%2==0;
}
);//返回[5,3,1]
every():数组判断。所有的,针对量词
some():数组判断。至少有一个,存在量词
返回布尔值,一旦确认会停止遍历
空数组时,every()返回true,some()返回
a=[1,2,3,4,5];
a.every(function(x){return x<10;});//true,所有值都大于10
a.some(function(x){return x%2==0});//ture,存在偶数
reduce():指定函数将数组元素进行组合,生成单个值。“注入”“折叠”。需要两个参数,第一个是执行化简操作的函数,(可选参数)第二个是传递给函数的初始值
var a=[1,2,3,4,5];
var sum=a.reduce(function(x,y){return x+y},0);//求和,初始值为0
var product=a.reduce(function(x,y){return x*y},1);//求积,初始值为1
var max=a.reduce(function(x,y){return (x>y?)}x:y});//求最大值,没有初始值
reduceRight():从低到高,从右到左执行reduce()
var a=[2,3,4];
//计算2^(3^4)
var big=a.reduceRight(
function(accumlator,value){
return Math.pow(value,accumlator);
}
);
reduceRight()和reduceRight()区别
var objects=[{x:1,a:1},{y:2,a:2},{z:3,a:3}];
var leftunion=objects.reduce(union);//{x:1,y:2,z:3,a:1}
var rightunion=objects.reduceRight(union);//{x:1,y:2,z:3,a:3}
indexOf():从头搜索,找到则返回第一个数的索引,找不到返回-1
lastIndenxOf():从尾搜索
a=[0,1,2,1,0];
a.indexOf(1);//1
a.indexOf(99);//-1
a,lastIndexOf(1);//3
判断是否为数组
Array.isArray([]);//true
[] instanceof Array;//true
({}).toString.apply([])==='[Object Array]';//true
[].constructor===Array;//true
布尔值
true //真值
undefined //假值(表示系统的、出乎意料或类似错误的值的空缺)
null //(表示程序级的、正常的或在意料之中的空缺)
0
-0
NaN
""
如果需要将null与0或“”区分来,需要进行显性比较
全局对象
全局属性:undefined、Infinity、NaN
全局函数:isNaN(()、parseInt()、eval()
构造函数:Data()、RegExp()、String()、Object()、Array()
全局对象:Math、JSON
1.通过“Global”找到全局对象,代码最顶级可以用this来引用全局对象
2.全局window对象可以用一个属性window引用自身,可以代替this
var global=this;//定义一个引用全局对象的全局变量
包装对象
存取字符串、数字或布尔值属性时创建的临时对象称作包装对象。修改只是发生在临时对象身上,而这个对象并未继续保留下来。
可以通过String()、Number()、Boolean()构造函数来显示创建包装对象。
var s ="test",n=1,b=true; //一个字符串、数字、布尔值
var S=new String(s); //一个字符串
var N=new Number(n); //一个数字
var B=new Boolean(b); //一个布尔对象
基本类型对象和包装对象的区别:
var str="string";
var strObj=new String("string");
JavaScript中的隐藏机制:
'str'-->String Object
123-->Number Object
true-->Boolean Object
对基本类型以对象的方式,访问、增加其属性操作时,会智能地将这个基本类型转换为对应的包装类型对象。访问之后,临时对象会销毁掉。
类型检测
typeof:返回字符串,适合函数和基本类型的判断
typeof 100 //"number"
typeof true //"boolean"
typeof function //"function"
typeof(undefined) //"nudefined"
typeof new Object() //"object"
typeof[1,2] //"object"
typeof NaN //"number"
typeof null //object
instanceof:判断对象类型,基于原型链判断
obj (对象) instanceof Object(函数对象)
[1,2] instanceof Array===true
new Object() instanceof Array===false
function Person(){}
function Student(){}
Student.prototype=new Person();//任何一个构造函数都有一个对象属性
Student.prototype.constructor=Student;
var bosn=new Student();//用bson创建Student实例
bosn instanceof Student; //返回true
var one=new Person();
one instanceof Person;//返回true
bosn instanceof Person();//返回true
bosn会有一个原型,指向它的构造器Student.prototype属性,发现Student.prototype不等于Person.prototype。通过原型链发现bosn原型的原型,等于Person.prototype
不同的window或iframe之间不能使用instanceof
Object.prototype.toString
constructor
duck type
不可变的原始值和可变的对象引用
1.原始值(undefined,null,布尔值、数字、字符串)是不可更改的
原始值的比较是值的比较,只有它们的值相等它们才相等
var s="hello";
s.toUpperCase(); //"HELLO",并未改变s的值
s; //"hello"
2.对象(普通对象、数组、函数)是可变的
对象的比较并非值的比较,而是引用对象的比较。引用同一个基对象时才相等
var o={x:1};
o.x=2; //通过修改对象属性更改对象
o.y=3; //通过添加新属性更改对象
var a=[1,2,3];
a[0]=0; //更改数组的一个元素
a[3]=4; //为数组增加一个元素
var o={x:1},p={x:1}
o===p //false
var a=[],b=[]
a===b //false
var a=[];
var b=a; //变量b引用同一个数组
b[0]=1; //通过b来修改引用的数组
a[0] //a[0]=1
a===b //true
3.显式复制对象的属性或数组,通过循环
var a=['a','b','c'];
var b=[];
for(var i =0;i<a.length;i++){
b[i]=a[i];
}
单独比较两个单独的对象或者数字,必须比较它们的属性或元素
function equalArrays(a,b){
if(a.length!=b.length){
return false;
}else{
for(var i=0;i<a.length;i++){
if(a[i]!==b[i]){
return false;
}else{
return true;
}
}
}
隐式类型转换
巧用+/-规则:
//把num变为数字
num+0
//把num转换成字符串
num+"
==等于
"1.23"==1.23
0==false
null==undefined
new Object()==new Object()
[1,2]==[1,2]
null==undefined相等
number==string转number
boolean==?转number
object==number|string尝试对象转为基本类型,其他为false
严格等于===
null===null
undefined===undefined
NaN不严格等于NaN
new Object不严格等于new Object
类型转换
1.原始值到原始值的转换
2.原始值到对象的转换,原始值通过调用String()、Number()、Boolean()构造函数,转化为各自的包装对象
一个值转换为另一个值,并不意味着两个值相等
显式类型转换
1.最简单的方法,通过Boolean()、Number()、String()、Object(),不通过new调用这些函数时,会作为类型转换函数做类型转换。根据上表。
x+"" //String(x)
+x //Number(x)
!!x //Boolean(x)
3.Number类定义的方法
(1)toString()方法,进行基于十进制的其他进制的转换
var n =17;
binary_string=n.toString(2); //10001
octal_string=n.toString(8); //021
hex_string=n.toString(16); //0x11
(2)toFixed(),根据小数点后的指定位数将数字转换为字符串
(3)toExponential()使用指数计数法将数字转换为指数形式的字符串,小数点前只有一位,小数点后位数右参数指定
(4)toPrecision()根据指定的有效数字位数将数字转换为字符串
注意:三个方法都会适当的进行四舍五入或填充0
var n=123456.789
n.toFixed(2); //123456.79
n.toExponential(3); //1.235e+5
toPrecision(7); //123456.8
toPrecision(10); //123456.7890
(5)parseInt()只解析整数,字符串前缀“0x”、“0X”解析为十六进制数
(6)parseFloat()可解析整数和浮点数
注意1:都是全局函数,不属于任何类的方法。
注意2:如果第一个非空格字符是非法的数字直接量,将最终放回NaN。
注意3:会跳过任意数量的前导空格,尽可能解析更多数值字符,并忽略后面的内容
parseInt("3 blind mice") //3
parseInt("0xFF") //255
parseFloat("3.14 meters") //3.14
parseInt(".1") //NaN
parseFloat("$72.2") //NaN
对象转换为原始值
1.对象到布尔值,都转换为true;包装对象亦是如此
new Boolean(false) //true
2.对象到字符串、对象到数字
只是用于本地对象,宿主对象(由web浏览器定义的对象)可以根据各自的算法转化为字符串、数字
3.所有对象继承了两个转换方法
(1)toString()
[1,2,3].toString() //"1,2,3"
(function(x){f(x);}).toString //"function(x){\n f(x); \n}"
/\d+/g.toString() //"/\\d+/g"
(2)valueOf()
默认的valueOf()方法简单地返回对象本身,而不是返回原始值;如果存在原始值,就默认将对象转换为原始值
var d =new Data(2017,6,1)
d.valueOf(); //返回1970年1月1日以来的毫秒数
变量的声明
未在var声明语句中给变量指定初始值,初始值就是undefined
变量作用域
全局变量:全局作用域,可以不用var声明
局部变量:优先级高于同名的全局变量,全局变量就被局部变量所掩盖。必须用var声明
var scope="global"
function checkscope(){
var scope ="local";
return scope;
}
checkscope(); //返回"local"
var scope ="global";
function f(){
console.log(scope); //输出"undefined",因为局部变量覆盖了全局变量
var scope="local"; //变量赋初始值,变量本身在整个函数体内都有定义
console.log(scope); //输出"local"
}
作为属性的变量
声明一个全局变量,实际是定义了全局变量的一个属性,创建的这个属性是不可配置的,无法通过delete运算符删除
var truevar =1; //申明一个不可删除的全局变量
fake var=2; //创建全局对象的一个可删除的属性
this.fakevar2=3; //创建全局对象的一个可删除的属性
delete truevar //false
delete fakevar //true
delete this.fakevar2 //true