在HTML中使用JavaScript
使用方式:<script>元素
<script>元素定义了6个属性
- async: 可选,表示应该立即下载脚本,但不应妨碍页面中的其它操作。只对外部脚本文件有效。
- charset:可选。表示通过scr属性指定的代码的字符集。
- defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。
- language:已废弃。原用于表示编些代码适应的脚本语言。
- src: 可选。表示包含要执行代码的外部文件。
- type:必选,可以看成language的替代属性,表示编写代码使用的脚本语言的内容类型(也称为MIME类型)。
不支持JavaScript情况可使用<noscript>元素
在HTML文档里添加里<noscript>元素的话,浏览器会在不支持脚本或者脚本被禁用的请况下会显示出来标签里的内容
JavaScript 基本概念
语法
- 区分大小写
- 标识符(变量、函数、属性等名字)
* 一个字符必须是一个字母、下划线(_)或者一个美元符号($);
* 其它可以是字母、下划线、美元符号或数字,但第一个字符不能是数字;
注释
// 单行注释
/*
* 这是一个多行
* (块级)注释
*/
严格模式
在严格模式下,一些不确定的行为将得到处理,而且对某些不安全的操作会抛出错误,写法如下
“use strict”
只在函数里使用
function doSomething() {
“use strict”
// 函数体
}
语句
ECMAScript中的一个语句以分号结尾,省去分号,则有解析器确定的语句结尾。
数据类型
- 基本数据类型: Undefined、Null、Boolean、Number、String;
- 复杂数据类型:Object;
判断数据类型可以使用 typeof 操作符
- 不要进行浮点数的运算,得到的精度不对,这是基于IEEE754数值的浮点计算的通病
Object类型
new Object();
Object是所用它的实例的基础,所以Object的属性和方法都存在与更具体的对象中,Object的每个实例都具有下列属性和方法:
- constructor:保存着用于创建当前对象的函数;
- hasOwnProperty(propertyName):用于检查给定的属性在当前对象实例中(而不是在实例的原型中)是否存在;
- isPrototypeOf(object):用于检查传入的对象是否是当前对象的原型;
- propertyIsEnumerable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举;
- toLocaleString():返回对象啊好难过的字符串表示,该字符串与执行环境的地区对应;
- toString():返回对象的字符串表示;
- valueOf():返回对象的字符串、数值、或布尔值表示。
引用类型
在ECMAScript中,引用类型 是一种数据结构,用于将数据和功能组织在一起
Object类型
创建方式
-
new 操作符后跟Object构造函数
var persion = new Object(); persion.name="LAW"; persion.age=24;
-
对象字面量
var persion = { name="LAW", age=24 }
最后一个属性的后面要是添加了逗号,会在IE7及更早版本和Opera中导致错误,不考虑这两种浏览器的话不会有影响的。
访问属性方式
- 点表示法
console.log(persion.name);
- 方括号表示法
var propertyName = "name"; console.log(persion[propertyName]); // console.log(persion["name"]);
正常情况下,工作中还是推荐点表示法的写法。只有在一些不确定属性名和属性名有特殊符号时可以灵活选择方括号法,可以减少不必要的代码量
Array类型
创建方式
-
Array构造函数
var colors = new Array();
-
数组字面量
var colors = [];
访问方式
console.log(color[num]);
检测是Array类型的方法
- instanceof 操作符
if(value instanceof Array) { // to do }
- Array.isArray() 方法
if(Array.isArray(value)) { // to do }
栈方法
栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,栈中项的插入和移除都发生在一个位置——栈的顶部。
- push 插入,返回插入后项数,会改变原来的数组。
var colors = new Array(); var count = colors.push("red", "green"); console.log(count) // 2
- pop 移除,返回数组的最后一项,会改变原来的数组。
var colors = ["red", "green"]; var item = colors.pop(); console.log(item) // "green"
队列方法
队列数据的访问规则是FIFO(First-In-First-Out),队列的列表末端添加项,从前端移除。
- shift 移除,返回数组的第一项,会改变原来的数组。
var colors = ["red", "green"]; var item = colors.shift(); console.log(item) // "red"
- unshift 插入,返回插入之后的项数,会改变原来的数组。
var colors = ["red", "green"]; var count = colors.unshift("black", "white"); console.log(count) // 4
重排序方法
-
reverse 对数组进行发转,会改变原来的数组。
var values = [1, 2, 3, 4, 5]; values.reverse(); console.log(values) // 5, 4, 3, 2, 1
-
sort 第一个参数数一个函数,根据函数来返回怎样排序
function compare(value1, value2) { if(value1 < value2){ return -1; } else if(value1 > value2){ return 1; } else (value1 = value2){ return 0; } } var values = [5, 4, 3, 2, 1]; values.reverse(compare); console.log(values) // 1, 2, 3, 4, 5
操作方法
- concat 合并数组,返回一个新数组,不会改变原来的数组。
var colors = ["red", "green"];
var colors1 = colors.concat("yellow", ["black"]);
console.log(colors); // ["red", "green"]
console.log(colors1); // ["red", "green", "yellow", "black"]
- slice 在数组中获取数组中一个或多项组成的新数组,一个参数就是以第一个参数开始到数组结束。两个参数就是以第一个参数开始,最后一个参数位置为止但不包括最后一个位置项,是一个左闭右开。
var colors = ["red", "green", "yellow", "black"];
var colors1 = colors.slice(1);
var colors2 = colors.slice(1, 3);
console.log(colors1); // ["green", "yellow", "black"]
console.log(colors2); // [ "green", "yellow"]
- splice 方法,可以实现删除、插入、替换功能。
- 删除: 需要两个参数,第二个参数为0
- 插入: 需要三个以上参数,第二个参数为0
- 替换:需要三个以上参数,第二个参数不为0
位置方法
- indexOf():接受两个参数,第一个是要查找的项,第二个是查找的起点。
- lastIndexOf():接受两个参数,第一个是要查找的项,第二个是查找的起点。但是查找的方向是从尾部开始。
迭代方法
下列的迭代方法都可以遍历数组,并不会改变原数组。
- every:每一项都要满足返回的条件,返回true。
- filter:过滤每一项,返回满足条件的所有项组成的数组。
- forEach:遍历每一项,无返回。
- map:遍历每一项,返回返回语句组成的数组。
- some:有一项满足返回的条件,返回true。
递归方法
- reduce:递归操作,如下
var value = [1, 2, 3]
var sum = arr.reduce((perv, cur, index, array) => {
return perv + cur;
});
console.log(sum); // 6
- reduceRight: 递归操作,与reduce反向递归
Date类型
ECMAScript中的Date类型是在早期Java中的java.util.Date累基础上构建的,因此使用的UTC(Coordinated Universal Time,国际协调时间)1970年1月1日午夜(零时)开始经过的毫秒数来保存日期,在存储格式的条件下,可以保存精确到1970年1月1日之前或者之后的100 000 000 天。
创建方式
new操作符和Date构造函数创建
var now = new Date();
两种获取毫秒数的方法
- parse 根据传入的日期字符串来转化成对应的毫秒数,根据地区传入的不同的字符串,
var someDate = new Date(Date.parse("May 25, 2004"));
如果直接将表示日期的字符串传入给Date构造函数,也会后台调用Date.parse(),上面代码下面是一样的
var someDate = new Date("May 25, 2004");
- UTC 根据传入的参数返回时间戳,参数分别是 年份、基于0的月份、天数、小时数、分钟、秒以及毫秒数。前两个参数是必须的,后面不传就默认是当前参数代表的开始日期。
// GMT时间2005年5月5日下午5:55:55 var allFives = new Date(Date.UTC(2005, 4, 5, 17, 55, 55));
Date构造函数也可以和模仿parse函数一样,模仿UTC,上面代码下面是一样的
var allFives = new Date(2005, 4, 5, 17, 55, 55);
获取当前时间戳的方法
- Date.now 返回表示调用这个方法时的日期和时间的毫秒数。
- +new Date() 返回表示调用这个方法时的日期和时间的毫秒数。
- new Date().valueOf() 返回表示调用这个方法时的日期和时间的毫秒数。
RegExp类型
ECMAScript通过RegExp类型来支持正则表达式,使用的语法与Perl类似
创建方式
- 字面量:
var expression = /pattern/flags;
- 模式(pattern):可以是任意简单或复杂的正则表达式
- 标志(flags):每一个正则表达式可以携带一个或多个标志,支持的标志有下列三种:
- g:表示全局(global)模式,即模式将应用与所以字符串,而不是匹配到一个之后就停止操作;
- i:表示不区分大小写;
- m:表示多行(multiline)模式,即到达一行末尾是否继续查找下一行;
- 使用RegExp构造函数:
var pattern = new RegExp(pattern, flags);
正则表达式里的模式中要是使用元字符,都需要转义,包含的元字符有: ( ) [ ] { } \ ^ $ ? * + . |
在RegExp构造函数里,模式是字符串,所以需要双重转义,即 /\?/ 等价与 “\\?”
RegExp实例属性
- global:布尔值,表示是否设置了g标志;
- ignorceCase:布尔值,表示是否设置了i标志;
- lastIndex:整数,表示开始搜索下一匹配项的字符位置,从0开始;
- multiline:布尔值,表示是否设置了m标志;
- source:正则表达式的字符串表示,按照字面量形式而非传入构造函数中的饭字符串模式返回;
var pattern1 = /\[bc\]at/i;
console.log(pattern1.global); // false
console.log(pattern1.ignorceCase); // true
console.log(pattern1.lastIndex); // 0
console.log(pattern1.multiline); // false
console.log(pattern1.source); // "\[bc\]at"
var pattern2 = new RegExp("\\[bc\\]at", "i")
console.log(pattern2.global); // false
console.log(pattern2.ignorceCase); // true
console.log(pattern2.lastIndex); // 0
console.log(pattern2.multiline); // false
console.log(pattern2.source); // "\[bc\]at"
RegExp实例方法
-
exec 专门为了捕获分组设计的,接受一个字符串参数,返回第一个匹配项信息的数组,或者没有匹配项返回null,返回的数组包含额外的两个属性:index和input,index表示匹配项在字符串的位置,input表示应该正则表达式的字符串。
正则表达式的模式里通过 () 来区分一个分组
var text = "mom and dad and baby"; var pattern = /mom( and dad( and baby)?)?/g; var matches = pattern.exec(text); console.log(matches.index); // 0 console.log(matches.input); // "mom and dad and baby" console.log(matches[0]); // "mom and dad and baby" console.log(matches[1]); // " and dad and baby" console.log(matches[2]); // " and baby" // g 模式下,exec会在字符串中继续查找新匹配的项,不设置 g 模式,都是从头开始找 var text1 = "cat bat"; var pattern1 = /.at/g; var matches1 = pattern1.exec(text1); console.log(matches1.index); // 0 console.log(matches1[0]); // "cat" console.log(pattern1.lastIndex); // 3 var matches2 = pattern1.exec(text1); console.log(matches2.index); // 4 console.log(matches2[0]); // "bat" console.log(pattern1.lastIndex); // 7
-
test 接受一个参数,根据模式是否与字符串匹配返回true或者false;
RegExp构造函数属性
- input: 最近一次要匹配的字符串;
- lastMatch:最近一次的匹配项;
- lastParen:最近一次的捕获组;
- leftContext: input字符串中lastMatch之前的文本;
- rightContext: input字符串中lastMatch之后的文本;
var text = "this has been a short summer";
var text1 = "this has been a short summer";
var pattern = /(.)hort/g;
var pattern1 = /(.)hort/g;
if (pattern.test(text)) {
console.log(RegExp.input); // "this has been a short summer"
console.log(RegExp.leftContext); // "this has been a"
console.log(RegExp.rightContext); // " summer"
console.log(RegExp.lastMatch); // "short"
console.log(RegExp.lastParen); // "s"
}
// 上面的构造函数的属性名都有对应的短属性名,如下
if (pattern1.test(text1)) {
console.log(RegExp.$_); // "this has been a short summer"
console.log(RegExp["$`"]); // "this has been a"
console.log(RegExp["$'"]); // " summer"
console.log(RegExp["$&"]); // "short"
console.log(RegExp["$+"]); // "s"
}
除了上面介绍的几个属性之外,还有多达9个用于存储捕获组的构造函数属性,RegExp.$1、RegExp.$2…RegExp.$9,分别用于存储第一、第二。。。第九个匹配的捕获组,在调用 exec() 或 test() 方法时,自动填充。
Function类型
在ECMAScript里,虽然有函数一名,但实质上是一个对象,所以也就没有重载只说,重复定义的函数下面的会覆盖上面的函数对象。
创建方式
-
函数声明方法
function sum(num1, num2) { return num1 + num2; }
-
函数表达式方法
记住一个观念,“函数是对象,函数名是指针”
var sun = function(num1, num2) { return num1 + num2; }
-
Function构造函数方法(不推荐使用)
这种语法会导致解析两次代码(第一次是解析常规ECMAScript代码,第二次是解析传入构造函数中的字符串),从而影响性能。
var sun = new Function("num1", "num2", "return num1 + num2");
函数内部属性
-
arguments:保存函数参数,这个对象有一个名叫callee的属性,是一个指针,指向拥有这个arguments对象的函数
在递归运算时,arguments的callee指针可以有效的解决函数执行与函数名紧密耦合问题;
callee指针有一个caller对象,保存着调用当前函数的函数的引用,可以使用它来窥视其它代码。
function factorial(num){ if(num <= 1){ return 1; } else { return num * factorial(num - 1); } } // 下面的与上面的代码一直 function factorial(num){ if(num <= 1){ return 1; } else { return num * arguments.callee(num - 1); } }
-
this:和大多数语言一样,this引用的时函数执行的环境对象。
函数属性和方法
属性
- length: 表示函数希望接受的命名参数的个数;
- prototype:保存函数所以实例方法,是不可枚举的,也就无法使用for-in来访问;
方法
- apply() 改变函数的作用域,就是改变来this的指向,第一个参数是函数运行的作用域,第二个是参数数组;
- call() 改变函数的作用域,就是改变来this的指向,第一个参数是函数运行的作用域,第二个是参数1,第三个是参数2…以此类推;
- bind() 会创建一个实例,其this值会被绑定到传入 bind() 函数的值
基本包装类型
在ECMAScript标准中,为了方便操作基本类型值,提供了三种包装类型:Boolean、Number、String;
使用场景
var s1 = "some text";
var s2 = s1.substring(2);
在上面代码中,声明类一个字符串变量s1,s1通过字面量创建的字符串本身是不具有任何方法和属性的,当执行第二行代码访问s1时,后台会自动执行下列处理
- 创建一个String类型的一个实例;
- 在实例上调用指定的方法;
- 销毁这个实例
可以将上三个步骤想成下列代码
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null;
注意:代码在后台自动创建的基本包装对象,则只存在于一行代码的执行瞬间,然后立即被销毁
使用new调用基本包装类型的构造函数,与直接调用同名的转型函数不一样
var value = "25";
var number = Number(value); // 转型函数
console.log(typeof numbder); // "number"
var obj = new Number(value); // 构造函数
console.log(typeof obj); // "object"
几个包装类型的常用方法和属性
Boolean类型
- toString() 返回boolean值的字符串形式
Number类型
- toFixed(精度);返回指定小数位的字符串;
- toExponential() ; 返回指定小数位的字符串,不过是科学表示法的形式;
- toString() 返回number值的字符串形式
string类型
- length:字符串类型值的长度;
- charAt(); 返回字符串指定位上的字符;
- charCodeAt(); 返回字符串指定位上的字符编码;
- concat(); 将一个或多个字符串拼接起来,返回新的字符串;
- slice(); 返回在原字符串上分割出来的新的字符串,传一个参数代表从某个位子开始到结束,两个代表从某个位子开始到另一个位子结束;
- substring(); 返回在原字符串上分割出来的新的字符串,传一个参数代表从某个位子开始到结束,两个代表从某个位子开始到另一个位子结束;
- substr(); 返回在原字符串上分割出来的新的字符串,传一个参数代表从某个位子开始到结束,两个代表从某个位子开始分割出来几个字符;
- indexof(); 传入一个参数,从头部开始向后搜索返回指定字符所在的位子,没有返回-1;传入第二个参数从指定位子开始搜索;
- lastIndexOf(); 传入一个参数,从尾部开始向后搜索返回指定字符所在的位子,没有返回-1;传入第二个参数从指定位子开始搜索;
- trim(); 去除字符串的前后空格;
- toLowerCase(); 返回字符串的小写字符串
- toLocaleLowerCase(); 返回字符串的小写字符串,针对特定地区实现;
- toUpperCase(); 返回字符串的大写字符串
- toLocaleUpperCase(); 返回字符串的大写字符串,针对特定地区实现;
- match(); 接受一个正则参数,返回匹配的索引数组;
- search(); 接受一个字符串或者正则参数,返回匹配到的索引,没有返回-1;
- replace(); 第一个参数是一个字符串或者正则,第二个参数是一个字符串或者有返回值的函数,用来替换匹配到的字符串,结合正则的分组机制,可以实现大多数的替换操作;
- split(); 按照指定的第一个参数字符串分割成一个数组,第二个参数是返回数组的个数;
- localeCompare(); 比较字符串与第一个参数,如果字符串排名在参数之前,返回一个-1,之后返回1,相等返回0;
- formCharCode();根据输入的字符串编码返回对应的字符串;