day3(12.18):JavaScript的基本概念和语法
本章内容
语法
数据类型
流控制语句
函数
语法
1、一切(变量、函数、操作符)区分大小写,所以typeof不能做函数名,但是typeOf可以。
2、标识符:数字字母下划线,数字不能放前面。用来表示变量、函数、属性的名字。或者函数的参数。采用驼峰大小写格式。
3、严格模式:一直不同的解析和执行模式,ECMAScript3的一些不确定行为会得到处理。使用方法:a、在整个脚本的顶部添加"use strict".b、在函数的内部的函数体上方添加"use strict"。
4、注释:单行//,多行/* */
5、语句用分号结尾,免得压缩的时候,出各种幺蛾子。条件语句和多条语句用{ } 括起来。
关键字和保留字
关键字:用来表示控制语句的开始或者结束,或者用于执行特定操作等。比如do if in for void
保留字:没有啥特定用途,但是可能在将来被用作关键字。就是保留起来,你先别用,以后老子还要用这些单词呢。比如int char long
变量
ECMAScript中的变量是松散类型,也就是可用来保存任何类型的数据。因此通过var定义一个变量message之后,可以先保存hi,再保存10.只是一个用于保存的占位符。
var确定变量的作用域。a、在函数中声明变量,那么作用域就是函数,函数外是无法访问的。b、在全局中声明,作用域就是全局,全局中的函数都可以访问。c、在函数中直接message = 123.那么作用域沿着作用域链一直向上查找到声明的地方,没有找到的话,那只能是全局了,毕竟都找到“全局”这个地方了,总不能又往下跑吧。
其他:
var可以一次声明多个变量。
另外在严格模式下,不能声明名字为eval和arguments的变量。
var声明会提前,比如先执行函数console.log(message),后声明var message = “王海洋真好看”,这是一点问题都没有的,首先因为王海洋真的很好看,其次因为var声明提前到函数执行之前。关于声明提前,另外一个注意的地方是,声明提前没有块级作用域,比如if(){var message = “王海洋真好看”},这里的if语句不是函数体,会提前到全局的前面。
数据类型
typeof
typeof可以判断值类型的string、undefined、Boolean、number
另外对于引用类型的object和array判断为object,对于引用类型的function判断为function。对于null判断为object,对于NaN判断为number。
详解以上:
1、undefined:声明了,但是没有初始化,就是undefined。比如
var message; console.log(message);其实相当于默认了var message = undefined。
对于声明了,但是没有初始化的message,alert(message) //undefined,alert(typeof message) //undefined
对于没有声明,没有初始化的age,alert(age) //产生错误 alert(typeof age) //undefined
2、Null:指向空对象的指针,所以是typeof 是object。如果生命一个对象,但是没有给他赋值,就初始化为null。不同于undefined,不用把一个值显式设置为undefined,因为默认就是这个。但是alert(null == undefined) 是true,这是因为双等是强制类型转化。在判断一个对象是否有某属性或者某个函数知否有某参数,使用双等,其他情况使用三等。Jquery就是这么干的。
3、Boolean:因为区分大小写,所以之后true和false为Boolean的字面量,TRUE,True等等都是标识符。另外所有类型的值,都有可以与Boolean进行转化,比如:String:" "转化为false,
number:0或NaN转换false,
object:null转换false,
Undefined:直接转换false,其他都是true。
强制类型转换方法有:a、双等号== b、控制语句比如 if(在这里强制类型转换){} 、c、逻辑运算比如 || . d、加号,比如10+"100"就是字符串"10100" 。另外今天刚看的Boolean()也可以。
4、Number类型:
十进制省略,八进制时候0开头,后面数字超过7,就变成了十进制,比如070是八进制,078就是十进制了。十六进制0x开头。
NaN ,typeof返回的时候,是number。0/0就是NaN,NaN的任何有一个操作,都是NaN,NaN不和任何值相等,包括NaN。有一个api:isNaN(),只要是能转化成数字的都是false,比如"10","true",返回fasle,"blue","NaN"返回true。
数值转化,Number()适合任何类型,parseInt(),parstFloat()只适合字符串类型。
Number()可以把非数值转化为数值。Boolean的true和false转化成1、0. undefined:转化为NaN ,null:转化为0。字符串比较复杂:只包含数字,转化为数字。前导0去掉,所以八进制也成了十进制;只包含十六进制,转化为十进制;空则转化为0,其余为NaN。对象:调用valueOf() 。比如"Hello world"、" "、"0011"、"true" 分别转化为NaN、0、11、1
parseInt():从头往后解析,空格跳过(所以""会被解析为NaN),第一个字符如果是非数字和符号,返回NaN(所以" good123"返回NaN),数字字符解析完了后,直接返回解析的数字字符,不管后面还有没有非数字字符("1234.5王海洋棒棒哒"返回1234)。另外,如果传入第二个参数,会根据第二个参数转化对应的进制,比如parseInt("10",2)转化为2进制的2.
parseFloat():与parseInt()解析过程类似,两个区别:只有遇到第二个小数点,才停止解析。“11.22.33”就解析为11.22 。没有第二个参数,十六进制,直接转化为0。只能解析十进制。
5、String类型
跟c语言差不多,只挑干货说一下,
第一、字符串一旦创建无法改变,比如var lang = "Java",那么lang = lang + "script" , 新建一个10个字符的字符串,原来的lang和"script"被无情地销毁,真是走狗烹啊。
第二、转化成字符串,两种方法,toString(),除了null和undefined之后,其余数值、布尔值、对象、字符串都有这个方法。一般不要参数,数值类型可以要参数,作为转化的基数,比如var number = 10 ,number.toString(16),转化成16进制为a。另一个String()可以转化任何类型,过程是:判断是否为null或者undefined,不是,则调用tostring,否则返回null或undefined。如String(null)为"null"。
6、Object类型
通过var o =new object()创建一个对象,object中属性和方法同样也在更具体的对象中。(扯来扯去就是继承的意思。)
每个对象都有的属性和方法:
constructor,保存用于创建当前对象的函数。也就是实例o的constructor指向object(),后面将会讲到的原型链里面还有,object.prototype的constructor指向object()。
hasOwnProperty(),判断这个属性是自己的属性, 还是从原型链继承的属性。
o1.isPrototypeOf(o2),判断o1是否为o2的原型对象。
propertyIsEnumerable(属性名):属性能否枚举出来。for-in时候可以判断一下。
toLocaleString/toString/(valueOf) 都是返回对象的字符串(字符串、数字、布尔)表示。
操作符
一元操作符
++,--。注意一下位置就行了。如果放在变量前面,代表"先进行++或者--,再运算",举个大栗子:var num1 = 10,num2=10,num3 = ++num1 + --num2 ,意思就是:先给num1执行++操作,也就是num1成了11,num2执行--操作,也就是num2成了9,再相加,得到20。
跟c语言里一毛一样,都没啥说的。注意一点是,可以用于字符串、布尔值、浮点数、对象。都是先转化为数值变量,然后再执行。这里会让数据类型发生变化。变成数值变量。false转化为0,true转化为1。当字符串没有数字的时候,自然只能转化为NaN,对于对象,使用valueOf()方法转化。比如s2="王海洋是个脸皮很厚的程序猿";s++,返回的就是NaN。类似,一元+/-也会改变变量类型。+s2也是一个NaN。
位操作符、乘性操作符、加性操作符、关系操作符、条件操作符、赋值操作符、逗号操作符 跟c语言一模一样,没啥好说的。跳过。
这里只重点说一下全等===和不全等==。不全等是先进行数据转化,然后比较,全等是不进行数据转化就进行比较。比如"55"==55是true,但是"55"===55就是false。然后!=和!==也是先进行相似的类型转换。
语句
if语句、do-while、while、for语句,同c语言,跳过。continue、break、switch语句与c语言相同,跳过。
for-in语句
可以用来枚举对象的属性。比如for (var propName in window){document.write(propName)} 就是一个枚举window对象所有属性的函数。这里的属性名最好声明一下,保证使用局部变量。注意对象的属性顺序是不可预测的,所以返回的顺序也是不一定的。在枚举之前,先检查对象是不是null或者undefined,免得抛出错误。
label语句
代码中添加标签,以便将来使用。比如:
var temp = 0;
start:for(var i = 0;i<=5;i++){
for(var j= 0;j<=5;j++){
if(i==1&&j==2){
break start;
} } }
标签一般与break,continue语句引用。加标签的语句,一般都要与for语句等循环语句配合使用。上面例子,start就是外面的for语句,没有这个,break只是跳出一层的循环。起名字时候注意语义性。
with语句
将代码的作用域设置在一个特定的对象中。比如经常用a = location.search.substring(1),b = location.hostname不是很方便,我们可以with(location){a = hostname},with语句代码块内部,每个变量首先被认为是一个局部变量,如果在局部环境中找不到该变量的定义,就会查询location对象中是否有同名属性。
函数
基本与c语言一致,其中对参数进行说明一下,
参数问题:JavaScript中,专门使用一个数组arguments来装传递来的参数。所以对函数和参数命名不能用arguments和eval。不管你函数定义的时候的参数传递来几个,调用的时候使用arguments数组进行存储就行了。比如定义时候传2个,调用的时候传递来4个,那么使用arguments[3]是没问题的。通过arguments.length可以获知多少个参数传递给了函数。因此开发人员可以使用arguments接收任意个参数(函数体中调用arguments[i]就好了)。并且arguments可以和命名参数可以一起使用。另外arguments和命名参数是同步的,比如函数体重把第一个参数赋值为0,那么arguments[0]成了0,反之亦然。但是内存空间是独立的。另外如果命名参数只有1个,你给arguments[1]赋值,不会反应到命名参数中。因为根本没有第二个命名参数啊。你说你咋反应过去嘛。没有赋值的命名参数会自动赋值为undefined。
没有重载:给一个函数名,定义两个函数体。只要接受的参数类型和数量不同就可以了。因为JavaScript不怎么在乎传递的命名参数,所以JavaScript中式没有函数重载的。后定义的会覆盖先定义的。所以如果想模仿重载,只有通过检查传入函数的类型和数量,然后做出不同的反应。
小结
基本类型:5个
不分浮点和整型,统一number
未指定返回值的函数返回undefined
没有函数签名的概念,也就是接受的参数类型和数量,统一用数组的形式传递。所以自然也没有重载了。传递任意多个参数,可以通过arguments对象来访问这些参数。