第一章 javascript简介
javascript的简介,有关js的一些历史问题。
js初期在不同的浏览器存在很大的兼容问题,但是慢慢的大家都在向标准靠拢,兼容问题已经好很多了。
我们通常会听到ECMAScript,它跟javascript是什么关系呢?
JS = ES + BOM(浏览器对象模型) + DOM(文档对象模型)
ES就是对javascript的类型,值,对象,属性,函数以及程序句法和语义,DOM就是ES运行在浏览器环境的时候,浏览器为其提供的扩展以实现更多更具体的功能(web浏览器只是ES实现肯能的环境之一,比如还有服务端的Node.js)。开发人员则可以通过BOM控制浏览器显示的页面以外的部分。
不过注意DOM并不是针对js的,很多别的语言也实现了DOM。
尽管众浏览器都实现了某些众所周知的共同特性,但其他特性还是会因浏览器而异。
第二章 在HTML中使用javascript
在页面中使用js的主要方法就是通过<script>元素,使用<script>元素的方法有两种
1. 直接在页面中嵌入js代码:
<script type="text/javascript">
function sayHi() {
alert("hi!");
}
</script>
但是在代码中使用 "</script>" 时,要使用转义字符 "\" ,不然会被当做代码的结束标签。如 alert("<\/script>"); 浏览器会弹出 "</script>"。
2. 包含外部文件:
<script type="text/javascript" src="example.js"></script>
标签位置
浏览器在解析到 <body> 标签时才开始呈现内容,将 <script> 元素放在 <head>元素中的话,则页面会等待所有 js 文件加载完才会呈现内容,在这之前页面都是影片空白。
因此通常将 <script> 放在 <body> 之后,</body> 之前。
所有<script>元素都会按照它们在页面中出现的先后次序依次被解析。在不使用defer和async属性的情况下,只有解析完前面的 <script> 元素中的代码之后才会开始解析后面 <script> 元素中的代码。
引入js代码的最佳做法
使用外部文件引入
优点:可维护性,可缓存,适应未来
文档模式
文档模式这个概念通过 doctype 切换实现, 最初包含两种模式:混杂模式和标准模式。
这两种模式主要影响CSS内容的呈现,某些情况下也会影响到 js 的解释执行。
随后IE又提出准标准模式,它与标准模式的差异几乎可以忽略。
第三章 基本概念
标识符:变量,函数,属性的名字,或者函数的参数。
规则:第一个字符必须是字母,下划线(_),美元符($),其他字符可以是字母,下划线,美元符,数字。
ES表示符习惯采用驼峰标记法,即第一个字母小写,剩下每个单词的首字母大写: firstSecond, myCar, doSomethingImportant
严格模式
严格模式是为javascript定义了一种不同的解析与执行模式。
严格模式下, ES3 中一些不确定的行为得到处理,对某些不安全的操作抛出错误。
严格模式下,javascript的执行效果会有很大不同。
要在整个脚本中使用严格模式,可以在顶部添加代码
"use strict" ;
在函数内部上方包含这条编译指示,可以指定函数在严格模式下执行:
function() {
"use strict";
//code
}
变量
ES的变量是松散类型的,可以保存任何类型的数据类型
定义变量时使用 var 操作符 (ES6 中新增了 const 与 let 操作符)。
使用 var 定义的变量将成为该变量的作用域中的局部变量。如果忽略 var 操作符,该变量将成为一个全局变量。
数据类型
ES有五种简单类型数据(基本类型数据):Undefined, Null, Boolean, Number, String 及一种复杂数据类型 Object
所有值都将是是上述六种数据类型之一
typeof 操作符
typeof是一个操作符而不是函数。
有六个可能的返回值
1. "undefined"
2. "boolean"
3. "string"
4. "number"
5. "object"
6. "function"
注意 typeof null 返回的是 "object" ,因为 null 的本意是一个空对象引用。
Undefined 类型
这个类型只有一个值: undefined
包含 undefined 值的变量与未定义的变量不同
var message;
//var age;
alert(message); //"undefined"
alert(age); // 报错
但是
typeof message 与 typeof age 都会返回 undefined值,尽管 age 是未声明的
Null类型
这个类型只有一个值 : null,它表示一个空对象指针。
Boolean类型
两个字面值: true, false(true不一定等于1, false 不一定等于0)
ES所有类型的值都有与这两个值等价的值,可以调用转型函数 Boolean() ,或者进行两次非操作 (!!)
true, 任何非空字符串,任何非零数值,任何对象都会在调用 Boolean() 时返回 true ( 包括空数组和空对象 [] , {} )
Number类型
可以表示整数和浮点数
八进制,第一个数是0(严格模式下八进制无效,会抛出错误)
Number.MIN_VALUE 保存了 ES 能表示的最小数值,大多数浏览器中这个是 5e-324
Number.MAX_VALUE 1.7976931348623157e+308
数值超出范围时会被表示为 Infinity 与 -Infinity
NaN
not a number
两个特点: 任何涉及 NaN 的操作都会返回 NaN , NaN 与任何值都不相等,包括自身
isNaN() 任何不能转换为数值的值都会被返回 true
数值转换
Number() 与 parseInt()
前者在转换字符串时比较复杂且不够合理,处理整数时更常用的是后者
parseInt() 在转换字符串时:它会先找到第一个非空格字符,如过第一个字符不是数字或者负号, 这个函数立即返回 NaN(因此空字符会返回NaN)。
如果第一个字符是数字,则继续解析第二个字符,直到解析完后面字符或者遇到第一个非数字字符(小数点会被当成非数字字符)。
parseInt() 可以识别各种整数格式
parseInt("070"); // 56(ES3) 70(ES5) (8进制)
parsetInt("0xf"); // 15(16进制)
ES5 中parseInt() 已经不具备解析八进制数值的能力。为了避免上面那种问题
可以为 parseInt() 提供第二个参数(转换时使用的基数,即将传入的第一个参数按这个基数来解析)
parseInt("AF",16); //175
parseInt("AF"); //NaN
这时可以解析八进制,指定基数会影响到转换的输出结果。
建议:无论什么情况下都明确指定基数。
parseFloat() 也是从第一个字符开始解析每个字符,也一直解析到字符末尾,直到遇到第一个无效的浮点数数字字符为止。因此,第一个小数点是有效的,第二个小数点就是无效的了,第二个小数点后面的字符串将被忽略。
parseFloat() 只解析十进制值(因此十六进制的数始终会被解析为0),没有第二个参数制定基数。另,如果字符串包含的是一个可解析为整数的数(没有小数点或者小数点后为0),会返回整数。
(空字符串也会返回NaN)
String 类型
转义字符:用于表示非打印字符或者具有其他用途的字符。例如 : \n ,\t, \b, \r
字符串的特点
ES中的字符串是不可变的,一旦创建,其值不可改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后用另一个包含新值的字符串填充该变量。
转换为字符串
数值,布尔值,对象和字符串都有一个 toString() 方法,但 null 和 undefined 没有这个方法。
通常这个方法不必传递参数,但是调用数值的 toString() 方法时,可以传递一个参数:输出数值的基数。默认情况下返回十进制。
注意
var a = 010;
a.toString(); // 8 (chrome)
如果知道转换的值不是 null 或者 undefined,也可以使用转型函数 String() ,能够将任何类型的值转换为字符串:如果有 toString() 方法,则调用这个方法。对于 null 会返回 "null" , undefined 会返回 "undefined"。
tips :要把某个值转换为字符串可以使用加号操作符,把它与一个字符串 ("") 加在一起。
Object 类型
如果不给构造函数参数,则可以省略后面那一对圆括号(var o = Object),但是不推荐。
一个重要思想:ES中,Object类型是所有它的实例的基础,Object类型所具有的任何属性和方法也同样存在更具体的对象中。
Object 每个实例都有下面属性与方法
- constructor
- hasOwnProperty(propertyName)
- isPrototypeOf
- propertyIsEnumerable(propertyName)
- toLocaleString()
- toString()
- valueOf()
操作符
自增,自减操作符在不包含有效数字的字符串时,将变量的值设为 NaN ,false 会先被转换为0,true 会先被转换为 1。
一元加和减操作符:对非数值应用一元加操作符时,会像 Number() 转型函数一样对这个值进行转换。
位操作符:
第三十二位表示符号,0 表示正数,1 表示负数。
对数值应用位操作时,内部都是64位数值先转换为32位数值,进行位操作之后再转换为64位数值。进行位操作时,NaN 和 Infinity 会被当做 0 来处理。
按位非操作的实质就是操作数的赋值减一。还有按位与(&),按位或( | ),按位异或(^)。
左移:(<<)空位用 0 填补
有符号右移:(>>)空位用符号位填补。
无符号右移:(>>>)用 0 填补空位 。通常负数无符号右移的结果会非常大。
布尔操作符
逻辑非(!):返回 false 的情况 : 操作数是对象,操作数是一个非空字符串,操作数是非 0 的任意数值(包括Infinity)
返回 true 的情况 : 操作数是空字符串,0, null, NaN, undefined
tips:同时使用两个逻辑非操作符,实际就会模拟Boolean() 转型函数的行为。最终结果与对这个值使用Boolean() 函数相同。
逻辑与(&&):返回两个操作数中的一个。当第一个操作数为真的时候,返回第二个操作数。第一个操作数为假的时候,直接返回第一个操作数。逻辑与是一个短路操作符,当第一个操作数能决定结果的时候,那就不会再对第二个操作数求值(就算第二个值原本未声明会导致报错)。
逻辑或(||):返回两个操作数中的一个。当第一个操作数为真的时候,返回第一个操作数,第一个操作数为假的时候返回第二个操作数。他也是一个短路操作符,第一个操作数为真,即第一个操作数就能决定结果的时候,就不会再对第二个操作数求值。
可以用这一行为来避免为变量赋null 值或者undefined 值。
乘性操作符
包括乘法,除法,求模(取余)。
加性操作符
1.加法:在有一个操作数是字符串的情况下,会将另一个操作数转换为字符串,然后将两个字符串拼接起来。
2.减法:如果一个操作数是字符串,布尔值,null,undefined,则先在后台调用 Number() 函数将其转换为数值。如果转换结果为NaN,则计算结果就是NaN。
如果一个操作数是对象,先调用valueOf() ,如果得到NaN,则结果就是NaN。没有valueOf() 方法的话就调用toString() 方法取得字符串并得到数值。
关系操作
<, >, <=, >= 它们都返回一个布尔值。
1.都是数值的话则进行数值比较。
2.都是字符串的话则比较字符编码值。
3.一个操作数是数值的话,将另一个操作数转换为数值再比较。
4.如果一个操作数是布尔值,则将其转换为数值,再比较。
5.对象。调用valueOf() 或者toString() 方法后再比较。
"23" > "3"; //false
"23" > 3; //true 注意转换规则
NaN > 3; //false
NaN <= 3; //false
"a" < 3; //false a 这时候被转换为 NaN
"a" >= 3; //false
相等操作符:相等和不相等,全等和不全等
1相等和不相等:
这两个操作符在比较之前都会先转换操作数(强制转型),再比较相等性。
1.如果有比较值为布尔值,则先将 true 转换为1,false 转换为 0。
2.一个操作数为字符串,一个操作数为数值,则先将字符转换为数值。
3.一个操作符是对象,而另一个不是的话,则调用 valueOf() 方法,得到的基本类型值按前面方法进行比较。
规则
1.null 与 undefined 相等
2.比较相等性之前,不能将null 和 undefined 转换为任何其他值。
3.如果有一个数是NaN,则相等操作符返回false。即使两个数都是NaN,相等操作符也不会返回 true。
4.如果两个操作数都是对象,只有这两个操作数指向同一个对象的时候,相等操作符才会返回true。
2.全等和不全等
全等操作符只在两个操作数未经转换就相等的情况下才会返回 true。这时 null === undefined 会返回false,因为它们类型不同。
if ([]) {
alert(1);
}
if ([] == true) {
alert(2);
}
if ([] == false) {
alert(3);
}
//1
//3
当直接传入空数组的时候,调用的是 Boolean() 转型函数,空数组是一个对象,这时候被转换为 true ,因此可以执行大括号里的语句。
但是当使用相等操作符的时候,由于含有布尔值,布尔值会转变成数值,[] 这时候调用的是 Number() 转型函数,这时候就是 0 。
函数
理解参数
arguments 对象只是与数组类似,并不是Array的实例。
arguments的值永远与对应命名参数保持同步。
notice:如果只传入了一个值,arguments[1] 设置的值不会反应到命名参数中。没有传递值的命名参数将自动被赋予undefined 值。
function add(num1, num2) {
arguments[1] = 10;
alert(arguments[0] + num2);
}
add(10); // NaN
add(10,20); // 20
add(10,30); //20
不能重载。