javascript数据类型和变量
js是弱类型语言,支持变量声明,存在作用范围,有局部变量和全局变量之分。
1.定义变量
隐式定义:直接给变量赋值;
现实定义:使用var关键字定义变量。
隐式定义:
<script type="text/javascript">
a="See me";
alert(a);
</script>
显示定义:
<script type="text/javascript">
var a="See me";
alert(a);
</script>
2.类型转换
js支持自动类型转换:
<script type="text/javascript">
var a="3.125";
var b=a-2;
var c=a+2;
alert(b+"\n"+c);
</script>
减号自动识别为算术运算,加号识别为字符串运算。
强制类型转换:
toString():将布尔值,数值等转换为字符串
parseInt():将字符串,布尔值等转换为整型
parseFloat():将字符串,布尔值等转换为浮点型
其中parseInt()和parseFloat()只能将带数字的字符串且开头是数字的数字部分转换。
<script type="text/javascript">
var a="3.125";
var b=parseFloat(a)+2;
alert(b);
</script>
3.作用域
全局变量:在全局范围(不在函数内)定义的变量,不使用var定义的变量。可以被所有脚本访问;
局部变量:在函数内定义的变量,只在函数内有效。当局部变量与全局变量同名时,局部变量会覆盖全局变量。
4.变量提升
<script type="text/javascript">
var a="全局变量";
function test(){
document.writeln(a + "<br>");
var a="局部变量";
document.writeln(a + "<br>");
}
test();
</script>
之所以发上上述情况,是因为js运行机制使得变量声明总是被解释器提升到函数体的顶部,上述程序等同于如下代码:
<script type="text/javascript">
var a="全局变量";
function test(){
var a;
document.writeln(a + "<br>");
var a="局部变量";
document.writeln(a + "<br>");
}
test();
</script>
变量提升只是提升变量的声明部分,而不是提升变量的赋值部分。
基本数据类型
JavaScript中有五种基本数据类型,它们分别是:数值类型,布尔类型,字符串类型,undefined类型,null类型。
undefined类型只有一个值,这个值就是它自己本身(undefined),在使用var声明变量但未对其进行初始化时,比较这个变量与undefined字面量,结果表明它们是相等的。
数值类型
与强类型语言如C、Java不同,JavaScript的数值类型不仅包括所有的整形变量,也包括所有的浮点型变量。JavaScript语言中的数值都是以IEEE 754双精度浮点数格式保存。JavaScript中的数值形势非常丰富,完全支持用科学计数法表示。科学计数法形如5.12e2代表5.12乘以10的2次方,5.12E2也代表5.12乘以10的2次方。
科学计数法中E为间隔符号,E不区分大小写。
当数值类型超出了其表述范围时,将出现两个特殊值:Infinity(正无穷大)和-Infinity(负无穷大。)
字符串类型
JavaScript的子串富川必须用引号括起来,此处的引号既可以是单引号,也可以是双引号。
注意:JavaScript和Java中的字符串主要有两点区别:
(1)JavaScript中的字符串可以用单引号括起来;
(2)JavaScript中比较两个字符串的字符序列是否相等使用 == 即可,无需使用equals()方法。
JavaScript以String内建类表示字符串,String类里包含了一系列方法操作字符串,String类有如下基本方法和属性操作字符串:
(1)charCodeAt() :返回字符串中特定索引处的字符所对应的Unicode值
(2)Legth():返回字符串的长度
(3)toUpperCase() : 将stringObj中的小写字母全部转成大写字母
(4)toLowerCase() :将stringObj中的大写字母全部转成小写字母
(5)fromCharCode() :直接通过String类调用方法,将一系列Unicode值转换成字符串
(6)indexOf() :返回字符串第一次出现的位置
(7)lastIndexOf() :返回字符串最后一次出现的位置
(8)subString() :截取stringObj从start开始,至end为止之前的所有字符,即包括start处的字符,但不包含end处的字符
(9)slice() :截取stringObj从start开始,到end为止之前的所有字符;即包括start处的字符,但不包括end处的字符。start与end均可为负值,当为负值时,表示从最后一个字符算起的第n个字符,比如-1表示最后一个字符,-2表示倒数第二个字符。
(10)match() :在字符串内检索指定的正则表达式的匹配结果,该结果与regexp是否有指定全局标志g有关
(11)split() :将separtor为为分隔,将stringObj分割成一个字符串数组。separator可以是字符串或者正则表达式,若为字符串,则以separator为分割符;弱separator为正则表达式,则以符合separator指定模式的字符串作为分隔符。
(12)replace() :将字符串中某个子串以特定字符串替代。
null类型:
null类型和undefined类型一样,这个值也就是它本身。从逻辑角度,null值表示一个空对象指针。如果定义的变量将用于保存对象,最好将该变量初始化为null。
boolean类型
bool值就只有两个值,true和false。任何数据类型要将一个值转换相应的boolean值,可以调用函数boolean();
复合类型
1、Object:对象
(1)对象:是一系列命名变量和函数的集合
(2)对象中的命名变量称为属性,而对象中的函数称为方法
(3)对象访问属性和函数的方法都是通过“.”
2、Array:数组
(1)数组是一系列的变量
(2)语法格式
A、var a = [1,2,3,4,5,6];
B、var b = [];
C、var c = new Array();
(3)数组的特征
JavaScript数组的长度可变
同一个数组里数组元素的类型可以互不相同
访问数组元素时不会产生数组越界,访问未赋值的数组元素时,该元素的值为undefined
3、Function:函数
(1)JavaScript函数无须声明返回值类型
(2)JavaScript函数无须声明形参类型
(3)JavaScript中函数可以独立存在,无须属于任何类
(4)JavaScript函数必须使用function关键字定义
运算符
JavaScript中运算符主要用于连接简单表达式,组成一个复杂的表达式。常见的有算数表达式、比较表达式、逻辑表达式、赋值表达式等,也有单目运算符,指操作原始表达式。大多数运算符都由标点符号组成(+、>=、!),也有关键字表示的运算符,如typeof、delete、instanceof等。
赋值运算符
赋值运算符用于给变量赋值,最常见的赋值运算符,当然就是等号,表达式x=y表示将y赋值给x。除此之外,JavaScript还提供其他11个赋值运算符。
x += y // 等同于 x = x + y
x -= y // 等同于 x = x - y
x *= y // 等同于 x = x * y
x /= y // 等同于 x = x / y
x %= y // 等同于 x = x % y
x >>= y // 等同于 x = x >> y
x <<= y // 等同于 x = x << y
x >>>= y // 等同于 x = x >>> y
x &= y // 等同于 x = x & y
x |= y // 等同于 x = x | y
x ^= y // 等同于 x = x ^ y
算数运算符
加法运算符(Addition):x + y
减法运算符(Subtraction): x - y
乘法运算符(Multiplication): x * y
除法运算符(Division):x / y
余数运算符(Remainder):x % y
自增运算符(Increment):++x 或者 x++
自减运算符(Decrement):–x 或者 x–
求负运算符(Negate):-x
数值运算符(Convert to number): +x
位运算符
或运算(or):符号为|,表示两个二进制位中有一个为1,则结果为1,否则为0。
与运算(and):符号为&,表示两个二进制位都为1,则结果为1,否则为0。
否运算(not):符号为~,表示将一个二进制位变成相反值。
异或运算(xor):符号为ˆ,表示两个二进制位中有且仅有一个为1时,结果为1,否则为0。
左移运算(left shift):符号为<<
右移运算(right shift):符号为>>
带符号位的右移运算(zero filled right shift):符号为>>>
比较运算符
比较运算符比较两个值,然后返回一个布尔值,表示是否满足比较条件。JavaScript提供了8个比较运算
== 相等
=== 严格相等
!=不相等
!== 严格不相等
< 小于
<= 小于或等于
>大于
>= 大于等于
逻辑运算符
逻辑运算符通常用于布尔值的操作,一般和关系运算符配合使用,有三个逻辑运算符:逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)。
逗号运算符
逗号运算符用于对两个表达式求值,并返回后一个表达式的值。
void
void运算符的作用是执行一个表达式,然后返回undefined。
流程控制
(1)顺序控制
(2)分支控制
让程序有选择的执行,分支控制有三种
①单分支②双分支③多分支
①单分支
if(条件表达式){
语句;
}
②双分支
if(条件表达式){
语句;
}else{
语句;
}
③多分支
if(条件表达式1){
//执行
}else if(条件表达式2){
//执行
}else if…{
//可以有多个else if
}
else{
//可以没有
}
多分支 switch
switch(条件表达式){
case 常量1:
语句; break;
case 常量2:
语句; break;
…
case 常量n:
语句; break;
default:
语句;
}
注意:case有几个都行,default可以没有。当case1~n都不满足的时候,则default。default并不一定要在最后。
(3)循环控制
循环控制有三种
①for循环
for(循环初值;循环条件;步长){
语句; //循环体
}
②while循环
while(循环条件){
语句; //循环体
}
特别说明:while循环是先判断再执行语句。
③do while循环
do{
语句;//循环体
}
while(循环条件);
特别说明:do while循环是先执行,再判断。
while和do while区别的通俗讲解:
还钱的问题
while:上来先问你还不还钱,还钱,就不打你(先判断,再执行)
do while:上来先打一顿,打完了再问,还钱吗(先执行,再判断)
函数
定义函数的3种方式
命名函数,匿名函数,使用Function类匿名函数。
递归函数
递归函数是一种特殊的函数,递归函数允许在函数定义中调用函数本身。
var factorial = function(n)
{
if (typeof(n) == "number")
{
if (n == 1)
{
return 1;
}
else
{
return n * factorial(n - 1);
}
}
else
{
alert("参数类型不对!");
}
}
alert(factorial(6));
局部变量和局部函数
如果局部变量和全局变量的变量名相同,局部变量会覆盖全局变量,局部变量只能在函数里访问,全部变量可以在所有的函数里访问。
局部函数与之类似,局部函数也在函数里定义,如:
function outer()
{
function inter1()
{
document.write("1111<br/>");
}
function inter2()
{
document.write("2222<br/>");
}
document.write("测试<br/>");
inter1();
niter2();
document.write("结束<br/>");
}
document.write("调用全局之前<br/>");
document.write("调用全局之后<br/>");
函数,方法,对象,变量,类
函数:函数可以被调用。
对象:定义一个函数时,系统也会创建一个对象,该对象是Function类的实例。
方法:定义一个函数时,该函数通常会附加给某个对象,作为该对象的方法。
变量:在定义函数的同时,也会得到一个变量。
类:在定义函数的同时,也得到一个与函数同名的类。
var hello = function(name)
{
return name + ",您好";
}
alert("hello是否为Function对象"+(hello instanceof Function)
+"\nhello是否为Object对象"+(hello instanceof Object));
alert(hello());
定义一个函数后,可以直接调用函数,也可以使用new关键字调用函数。
var test = function(name)
{
return "您好,"+name;
}
var rval = test('leegang');
var obj = new test('leegang');
alert(rval+"\n"+obj);
下面定义了一个Person函数,也就是定义了一个Person类,该Person函数也会作为Person类唯一的构造器。
function Person(name,age)
{
this.name = name;
this.age = age;
this.info = function()
{
document.writeln("我的名字是:"+this.name+"<br/>");
document.writeln("我的年级是:"+this.age+"<br/>");
};
}
var p = new Person('ly',26);
p.info();
函数的实例属性和类属性
函数中的变量
局部变量:在函数中以var声明的变量。
实例属性:在函数中以this前缀修饰的变量。
类属性:在函数中以函数名前缀修饰的变量。
看如下代码:
function Person(national,age)
{
this.age = age;
Person.national = national;
var bb = 0;
}
var p1 = new Person('中国',29);
document.writeln("创建第一个Person对象<br/>");
document.writeln("p1的age属性为"+p1.age+"<br/>");
document.writeln("p1的national属性为"+p1.national+"<br/>");
document.writeln("通过Person访问静态national属性为"+Person.national+"<br/>");
document.writeln("p1的bb属性为"+p1.bb+"<br/><hr/>");
var p2 = new Person('美国',32);
document.writeln("创建两个Person对象之后<br/>");
document.writeln("p1的age属性为"+p1.age+"<br/>");
document.writeln("p1的national属性为"+p1.national+"<br/>");
document.writeln("p2的age属性为"+p2.age+"<br/>");
document.writeln("p2的national属性为"+p2.national+"<br/>");
document.writeln("通过Person访问静态national属性为"+Person.national+"<br/>");
这里的this.age = age;是实例属性,也就是对象属性
Person.national = national是类属性,可以与java中的static一起理解
var bb = 0;这个是局部变量
调用函数的三种方式
直接调用函数
function fun(){
console.log("aaa");
}
fun();
用call方法调用函数
var each = function(array,fn){
for(var index in array){
fn.call(null,index,array[index]);
}
}
each([4,20,3],function(index,ele){
console.log(index+" " + ele);
})
这里面的call可以调用函数的引用,动态调用函数,call的第一个参数可以改变对象的作用域
和this的指向,为null时默认为全局作用域。
apply方法调用
这个和call是一样得到,就是传递参数的时候是1以数组的形式,对于参数很多的函数调用,很有用。
var each = function(array,fn){
for(var index in array){
fn.apply(null,[index,array[index]]);
}
}
each([4,20,3],function(index,ele){
console.log(index+" " + ele);
})
函数提升
典型的函数提升,就是在同一个<script…/>元素内,JS允许先调用函数,然后在后面再定义函数,举个简单的例子如下:
<script>
//先调用add函数
alert(add(2,5));
//后定义add函数
function add(a,b)
{
return a+b;
}
</script>
上面的代码先调用add()函数,再定义函数,完全可以正常执行.这是因为JS会将add()函数提升到<script…/>元素的顶端,也就是说,上面这段代码,和下面这段代码是一样的效果,代码如下:
<script>
//定义add函数
function add(a,b);
{
return a+b;
}
//调用add函数
alert(add(2,5))
</script>
局部函数会被提升到所在函数的顶部
例如如下代码:
<script>
function test()
{
//先调用add函数
alert(add(2,5));
//后定义add函数
function add(a,b)
{
return a+b;
}
}
test();
</script>
上面JS代码在test()函数中定义了一个局部函数add(),JS会将add()函数提升到test()函数的顶端,因此可以先调用add()函数,再定义.
特别注意: 如果局部函数为匿名函数,然后将匿名函数赋值给add局部变量,对于使用这种方式定义的函数,JS将只提升add变量,但函数定义本身并不会被提升.还是会发生如下报错:
面向对象
继承和prototype
所有的JavaScript对象之间并没有明显的继承关系。而且JavaScript是一种动态语言,它允许自由地为对象增加属性和方法。
当定义函数时,函数中以this修饰的变量是实例属性,如果某个属性值是函数时,即可认为该属性变成了方法。如下:
function Person(name,age){
this.name = name;
this.age = age;
this.info = function(){
document.writeln("姓名:" + this.name + "<br/>");
document.writeln("年龄:" + this.age + "<br/>");
}
}
var p1 = new Person('yeeku',29);
p1.info();
Person.prototype.walk = function(){
document.writeln(this.name + '正在慢慢溜达...<br/>');
}
document.writeln('<hr/>');
var p2 = new Person('leegang',30);
p2.info();
document.writeln('<hr/>');
p2.walk();
p1.walk();
通过使用prototype属性,可以对JS的内建类进行扩展。下面代码为JS内建类Array增加了indexof方法,该方法用于判断数组中是否包含了某元素。
Array.prototype.indexof = function(obj)
{
var result = -1;
for (var i=0;i<this.length;i++)
{
if(this[i] == obj)
{
result = i;
break;
}
}
return result;
}
var arr = [4,5,7,-2];
alert(arr.indexof(-2));
此外,JS类的prototype属性代表了该类的原型对象。在默认情况下,JS类的prototype属性值是一个Object对象,将JS类的prototype设为父类实例,可实现JS语言的继承。代码如下:
function Person(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log(this.name + "向您打招呼!");
}
}
var per = new Person('牛魔王',22);
per.sayHello();
function Student(name,age,grade){
this.grade = grade;
}
Student.prototype = new Person("未命名",0);
Student.prototype.intro = function(){
console.log("%s是个学生,读%d年级",this.name,this.grade);
}
var stu = new Student(5);
stu.name =("孙悟空");
console.log(stu instanceof Student );
console.log(stu instanceof Person );
stu.sayHello();
stu.intro();
构造器实现伪继承
下面再介绍一种伪继承的实现方式,代码如下:
function Person(name,age){
this.name = name;
this.age = age;
this.sayHello = function(){
console.log(this.name + "向您打招呼!");
}
}
var per = new Person('牛魔王',22);
per.sayHello();
function Student(name,age,grade){
this.inherit_temp = Person;
this.inherit_temp(name,age);
this.grade = grade;
}
Student.prototype.intro = function(){
console.log("%s是个学生,读%d年级",this.name,this.grade);
}
var stu = new Student("孙悟空",34,5);
console.log(stu instanceof Student );
console.log(stu instanceof Person );
stu.sayHello();
stu.intro();
this.inherit_temp = Person中将Person直接赋值给Student的inherit_temp实例属性,
this.inherit_temp(name,age)中以this为调用者,调用了Person构造器。
创建对象
JS创建对象的三种方式:
使用new关键字调用构造器创建对象。
使用Object类创建对象。
使用JSON语言创建对象。
下面举例使用JSON语言创建对象,代码如下:
person =
{
name : 'yeeku',
gender : 'male',
son : {
name:'nono',
grade:1
},
info : function()
{
document.writeln("姓名:"+this.name + "性别:" +this.gender);
}
}
person.info();
alert(person.son.name);
使用JSON语言创建对象时,属性值不仅可以是普通字符串,也可以是任何基本数据类型,还可以是函数、数组,甚至可以是另一个JSON语法创建的对象。
与使用JSON语法创建对象相似的是,数组的最后一个元素后面不能有逗号,如下代码定义一个更复杂的JSON对象。
var person = {
name : 'wawa',
age: 29,
schools : ['小学','中学',"大学"],
parents :[
{
name:'father',
age:60,
address:'广州'
}
,
{
name:'mother',
age:58,
address:'深圳'
}
]
};
alert(person.parents[0]);
document.writeln(person.parents[0].age);
document.writeln(person.parents[1].address);
实际上,JSON已经发展成一种轻量级的、跨语言的数据交换格式,因此JSON格式已成为XML数据交换格式的有力竞争者。