JavaScript程序设计基础篇

引用


1
document.write("hello,world!");

让文档写一个hello,world

JS特性

  • 运行环境:浏览器

  • 解释型: 不需要编译连接

DOM: Document Object Model 文档对象模型

浏览器中的JS分为两个部分,一部分 ECMAScript 定义了基本的语法

Javascript程序设计 -> DOM编程艺术

历史

1995 Netscape Navigator 2.0 js诞生

  • ECMAScript 1 1997年

  • W3C DOM 规范 1998年

  • ECMAScript 3 2000年

  • Ajax Web2.0 2005年

  • ECMAScript 5.1 2011年

  • ECMAScript 6 2015年

JS调试


JS 调试,需要用到开发者工具中的Source面板

command + o 查找文件

基本语法


字面量,直接量 var number = 1

标识符

  • 命名要求:以字母、下划线或者美元符号$开头
  • 由字母、下划线、美元符号$和数字组成
  • 不能以关键字为名称。
  • 大小写敏感

语句

1
2
3
4
if (sex == 1){

}
while

每个语句以分号结尾,每个语句结尾要加分号。

注释

  • 单行注释: //
  • 块级注释:以/*开头,以*/结尾
  • 不可嵌套

基本类型


Number String Boolean Object NuLL Undefined

整数、八进制(以0开头:070//56)、十六进制(0xff)、浮点数1.2(1.4E2 10的平方)、NaN(特殊值,不是一个数字)

[] 的bool值是true。 1 的bool 值是 true

“”是false null是false

Object

是一组无序的名值对的集合

NULL

值:null

出现场景:表示对象不存在,在未初始化时声明为null

Undefined

值:undefined

出现场景:以声明未赋值的变量,获取对象不存在的属性

类型识别 typeof

值类型和引用类型。

操作符

一元操作符

++ --

算数操作符

+ - * / %

关系操作符

> < >= <=

相等操作符

== != === !==

在做相等操作符 == 的时候,会进行类型转换。 bool类型值会转换为数字。 true会转换为1 。空字符串会转换为0

=== 全等,不会做类型转换。

逻辑操作符

! && ||

条件操作符

? :

逗号操作符

, 用于赋值操作。

对象操作符

new delete . [] instanceof in

new

1
var cat = new Object();

delete

1
2
3
4
var cat = {name: 'kitty', age:2};
alert(cat.name); // 'kitty'
delete cat.name;
alert(cat.name); // undefined

.

获取对象的属性

[]

通过[]获取值

1
2
3
var cat = {name:'kitty', age:2};
alert(cat.name); // 'kitty'
alert(cat['name']); // 'kitty'

instanceof

1
2
3
var cat = {name:'kitty', age:2};
alert(cat instanceof Object); // true
alert(cat instanceof Number); // false

判断是否是某个类型的实例

in

1
2
3
var cat = {name:'kitty', age:2};
alert('name' in cat); // true
alert('run' in cat); // false

判断某个属性是否属于一个实例

位操作符


~ & | ^ << >> >>>

语句


条件语句 | 循环语句 | with语句 | 异常捕获语句

循环语句 for-in

访问一个对象中每一个属性

1
2
3
4
5
6
7
8
9
10
11
12
var cat = {

name : 'kitty',
age : 2,
mew : function(){
console.log('喵喵喵');
}
}

for(var p in cat) {
document.write(p);
}

with语句


with(表达式){语句}

作用:把当前语句中代码的作用域指向到一个特殊的对象上。表达是一般是对象。

1
2
3
4
5
6
7
8
9
10
11
var kitty = {
age : 3,
friend: {
name: 'snoopy',
age : 2,
}
}

with(kitty.friend){
// 将作用域指向friend
}

异常捕获语句


try{
语句
} catch (exception){
语句
} finally {
语句
}

1
2
3
4
5
6
7
try{
document.write(notDefined);
} catch(error){
alert(error);
} finally {
alert('finally');
}

数值


函数:

  • Math.abs(x) // 获取绝对值

  • Math.round(x) // 四舍五入

  • Math.ceil(x) // 向上取整 1.1 -> 2 1.9 -> 2

  • Math.floor(x) // 向下取整

  • Math.max(…) // 获取最大值 Math.max(-1, -2, -3)

  • Math.min(…)

  • Math.random() // 随机数 范围:0<=x<1 区间的数值

  • Math.cos(x) // 以弧度为单位 返回余弦值

  • Math.exp(x) // 数值 返回 e的x次方

  • Math.log(x) // 数值 返回 e的y次方 = x 返回y的值

  • Math.sqrt(x) // 数值 返回 平方根

  • Math.pow(x, y)// 基数,指数 返回 x的y次方

parseInt(string, radix(输入几禁止的数))


1
2
3
4
parseInt('1.1') // 1
parseInt('1.9') // 1
parseInt('1b2.4') // 1 (解析b时无法解析,则返回1)
parseInt('www') // NaN(Not a Number)

parseFloat(String)


保留小数点

1
2
3
4
parseFloat('1.1') // 1.1
parseFloat('1.9') // 1.9
parseFloat('12.4b') // 12.4 (解析b时无法解析,则返回1)
parseFloat('www') // NaN(Not a Number)

Number(value)


1
2
3
Number(100.1) // 100.1
Number(12.4b5) // NaN
Number('www') // NaN

num.toFixed(digits) digits 表示保留几位小数 返回字符串

1
2
(100.123).toFixed(2) // "100.12"
(100.123).toFixed(0) // "100"

字符串


length属性,获取字符串的长度

str.charAt(index) 返回 字符

str.indexOf(searchValue, fromIndex) 返回 index

只返回匹配到的第一个要查询的符号

str.search(regexp(正则))

1
2
"micromajor163".search(/[0-9]/) // 10
"micromajor163".search(/[A-Z]/) // -1

str.match(regexp) -> 数组

1
2
3
4
"micromajor163".match(/[0-9]/)  // ["1"]
"micromajor163".match(/[0-9]/g) // ["1","6","3"] g为参数
"micromajor163".match(/[A-Z]/) // null
得到了字符串里面所有数字的集合

正则里面的全局参数决定了match输出单个还是输出集合

str.replace(regexp|substr, newSubstr | function)

如果不注明全局 g ,只替换第一个匹配的字符

1
2
3
4
"micromajor163".replace("163", "###")  // "micromajor###"
"micromajor163".replace(/[0-9]/, "#") // "micromajor#63"
"micromajor163".replace(/[0-9]/g, "#") // "micromajor###"
"micromajor163".replace(/[0-9]/g, "") // "micromajor"

str.substring(indexA[, indexB]) 截取 []表示第二个参数可以没有

A包含,B不包含

第二个参数不写表示后面所有的字符串都会被截取

1
2
"micromajor".substring(5,7) // "ma" 
"micromajor".substring(5) // "major"

关于课程中所说的substring不能传负数的说法,严格意义上是不准确的。其实substring可以传入负数,但是负数对substring是没有任何意义的,都会处理成0,所以我们可以理解为substring其实不支持负数。

str.slice(beginSlice[, endSlice]) (也是截取)

begin包含,end不包含

1
2
3
4
"micromajor".slice(5,7)  // "ma" 
"micromajor".slice(5) // "major"
"micromajor".slice(1,-1) // "icromajo" (负数表示从后往前数)
"micromajor".slice(-3) // "jor"

str.substr(start[,length])

从5开始 取两个

1
2
"micromajor".substr(5,2) // "ma"
"micromajor".substr(5) // "major"

str.split([separator][,limit]) 通过某个字符分割字符串

1
2
3
"micro major".split(" ")    // ["micro", "major"]
"micro major".split(" ", 1) // ["micro"]
"micro2major".split(/[0-9]/)// ["micro", "major"]

str.toLowerCase() 转化为小写 str.toUpperCase()

1
2
"MicroMajor".toLowerCase() // "micromajor"
"MicroMajor".toUpperCase() // "MICROMAJOR"

连接 +

1
"0571" + "-" + "88888888"

String() 把值转化为 字符串

1
2
String(163)  // "163"
String(null) // "null"

转译

1
2
3
"micro\"major" // "micro"major"
"micro\\major" // "micro\major"
"micro\tmajor" // "micro major"

对象


创建对象

1
2
var car = new Object()
var car = {}

属性和方法:

1
2
3
4
var car = {
color:"red"
run: function(){alert("run")}
}

增加属性和方法,修改属性

删除属性和方法

1
2
3
4
5
var car = {
color : "red",
run : function(){alert("run")}
};
delete car.color;

obj.constructor 来找到是由哪个图纸构建出来的

1
2
3
4
5
6
7
8
var car = {
color : "red",
run : function(){alert("run")}
};
car.constructor; // Object

var num = new Number(123);
num.constructor // Number

obj.toString() 将对象转为字符串

obj.valueOf() 获取对象的原始值

obj.hasOwnproperty()

1
2
3
4
5
6
var car = {
color : "red",
run : function(){alert("run")}
};
car.hasOwnProperty("color") // true
car.hasOwnProperty("logo") // false

数组


创建数组

1
2
3
4
var array = new Array();
var array = [];

var array = [1, 6, 3];

length

arr.indexOf(searchElement[,fromIndex = 0])

1
2
3
var telephones = [110, 120, 114];
telephones.indexOf(120); // 1
telephones.indexOf(119); // -1

arr.forEach(callback[, thisArg]) 遍历

每遍历一个元素,就会调用callback

1
2
3
4
5
6
7
8
9
var student = [
{id: 1, score: 80},
{id: 2, score: 50},
{id: 3, score: 70}
];
var editScore = function(item, index, array){
item.score += 5;
};
students.forEach(editScore);

arr.reverse() 将数组倒序

arr.sort(compareFunction)

sort放改变原来的数组

1
2
3
4
5
6
7
8
9
10
11
var student = [
{id: 1, score: 80},
{id: 2, score: 50},
{id: 3, score: 70}
];

var byScore = function(a, b){
return b.score - a.score;
};

students.sort(byScore);

如果不传入回调方法,则会按默认编码顺序。

arr.push(element1,…)

push将元素添加到数组的最后。

arr.unshift(element1,…)

将元素添加到数组的前面

arr.shift()

返回数组第一个元素,而且数组中的第一个元素被移除了。

arr.pop()

返回数组最后一个元素,并且将原来数组中的最后一个元素移除了。

arr.splice(index,howMany[,ele1[]])

1
2
3
4
5
6
student.
(1,1,{id:4, score:90})
从索引为1 的位置,删掉一个1个元素,并且加入{id:4, score:90}的元素

student.splice(1, 0,{id: 4,score:90})
在索引为1 的位置,往前插入一个元素

以上方法都改变了原来的数组

arr.slice(begin[,end]) 从区间拷贝出来一份数组

begin 包含,end不包含

如果end不传,则从begin开始一直到最后一个元素

arr.concat(value1,…,valueN)

做连接,连多个值,将很多个值连起来组成一个新的数组

1
var newStudent = student1.concat(student2, student3)

arr.join([separator])

将数组中的每个元素用分号连接起来

1
2
3
4
var emails = ["wq@163.com", "gp@163.com", "xl@163.com"];
emails.join(";"); // "wq@163.com;gp@163.com;xl@163.com"

// 如果什么都不填,默认使用,

arr.map(callback[,thisArg])

1
2
3
4
5
6
var scores = [60, 70, 80, 90];
var addScore = function(item, index, array) {
return item + 5;
};

scores.map(addScore); // [65, 75, 85, 95] 会返回一个新的数组

arr.reduce(callback,[initialValue])

1
2
3
4
5
6
7
8
9
10
11
var student = [
{id: 1, score: 80},
{id: 2, score: 50},
{id: 3, score: 70}
];

var sum = function(previousResult, item, index, array) {
return previousResult + item.score;
};

students.reduce(sum, 0);

以上这些方法 对原来的数组没有修改

函数


function 函数名([行参列表]){
执行代码
}

函数名([实参列表])

当实参数量多于形参

当实参数量多于形参,如何取到传入的参数

在给函数传入实参时,有一个隐藏的参数arguments

如果参数为对象类型: 则引用传递!

作用域

函数创建了一个作用域。变量的作用域就是变量起作用的范围

变量的作用域:从定义变量的那一行开始,直到所在的代码块结束

函数作为对象属性

构造函数

构造函数调用的结果,相当于return this

原型

1
2
3
4
5
6
7
8
9
10
11
function Point(x, y) {
this.x = x;
this.y = y;
}

Point.prototype.move = function(stepX, stepY) {
this.x += stepX;
this.y += stepY;
};

var point = new Point(1, 1);

调用构造函数,var point = new Point(1, 1); // {x = 1; y = 1}

然而,point 也可以调用move方法。 move是个隐藏方法

这样就可以用很节约的方法,创造大量的对象,且对象也会拥有强大的功能。

Date 日期


当前时间 new Date();

2014年12月5日 new Date(2014, 11, 5) 注意月份从0开始

创建日期

  • new Date() 获取当前日期
  • new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]])

new Date(1978, 11) 1978-12-01 00:00:00

new Date(2001, 8, 11) 2001-09-11 00:00:00

newDate(2015, 7, 20, 14, 57, 18) 2015-08-20 14:57:18

date.getXXX() 格式化

1
2
3
4
5
6
7
8
9
10
11
12
function padding(number) {
return number < 10 ? '0' + number : '' + number;
}

function format(data) {
return date.getFullYear() + '-'
+ padding(date.getMonth() + 1) + '-'
+ padding(date.getDate()) + ' '
+ padding(date.getHours()) + ':'
+ padding(date.getMinutes()) + ':'
+ padding(date.getSeconds());
}

padding的作用:如果获取的是个位数,会在前面补0

date.setXXX()

如果date.setDate(35); -> 会将天数加到下个月,以此类推

案例: 获取指定月数的天数

new Date(2001, 2, 0) -> 2001 - 02 - 28 00:00:00

1
2
3
4
5
6
function getDays(year, month) {
var date = new Date(year, month, 0);
return date.getDate();
}

alert('2001年2月有' + getDays(2001, 2) + '天。');

Date -> Number

date.getTime(); // 距离1970年 1月 1日 0时0分0秒

RegExp 正则表达式


描述字符串规则的表达式

  • /pattern规则/attrs属性
  • new RegExp(pattern, attrs)

regexObj.test(str)

test只需要被指定字符串包含正则表达式所描述字符串。

1
2
3
4
5
/13566668888/.test('13566668888'); // false
/135666688888/.test('13566668888'); // true

// 错误:
/aa135666688888bb/.test('13566668888'); // true

锚点

匹配一个位置

  • ^ : 其实位置 /^http:/ 表示以http为起始的url

  • $ : 结尾位置 /\.jpg&/ 表示以.jpg结尾的字符串

  • \b: 单词边界 /\bis\b/ 表示是否包含 is 这个单词

1
/^135666688888$/.test('13566668888'); // true

字符类

匹配一类字符中的一个

  • [abc]: a或b或c
  • [0-9]: 一个数字 [^0-9]:非数字的一个字符
  • [a-z]: 一个字母
  • . :任意字符(换行除外)
1
/^[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]$/.test('13566668888'); // true

字符类

具有特殊意义的字符

  • ^、$、\b
  • \d <==> [0-9] 数字 \D <==> [^\d] 非数字
  • \s <==> 空白符 \S <==> [^\s]
  • \w <==> [A-Za-z0-9_] \W <==> [^\W] 非单词字符
1
2
3
4
5
/\d/.test('123')  // true
/\d/.test('1ab') // true

/\D/.test('1ab') // true
/\D/.test('112') // false

简化:

1
/^1\d\d\d\d\d\d\d\d\d\d$/.test('13566668888'); // true

量词

表示出现的次数:

点星加问号

  • {m,n}表示 m到n次
  • * 表示{0,} 出现0到任意多次
  • ? : {0,1} 表示出现0 到 1次
  • + : {1,} 表示至少出现1次
1
2
3
4
5
6
7
/\d*/.test('abc') // true
/\d+/.test('abc') // false
/\d+/.test('1abc') // true

/\https?:/.test('http://www.163.com') // true s?表示s出现0到1次
/\https?:/.test('https://www.163.com') // true
/\https?:/.test('httpss://www.163.com') // false

简化:

1
/^1\d{10}$/.test('13566668888'); // true

转义符

需要匹配的字符是元字符

/^http:\/\//
/@163\.com$/

1
2
3
4
5
/@163\.com$/.test('abc@163.com')  // true

// 如果不转义,.表示任意字符
/@163.com$/.test('abc@163.com') // true
/@163.com$/.test('abc@163acom') // true

多选分支

/thi(c|n)k |表示多选分支,表示能匹配 thick 或 think ()表示限定范围

等价于 /thi[cn]k/

例子:检测一个图片是否是图片文件 /\.(png|jpg|jpeg|gif)$/

捕获

保存匹配到的字符串。

() :捕获

带括号的内容可以把匹配到的字符保存下来

(?:) 不需要捕获

使用:

  • $1, $2...
  • api参数或返回值

str.match(regexp)

获取匹配的字符串

分析案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var url = 'http://blog.163.com/album?id=1#comment';

var reg = /(^https?:)\/\/([^\/]+)(\/[^\?]*)?(\?[^#]*)?(#.*)?$/;

/*
分析:

第一个括号:?表示出现0,1次
第二个括号:[] 表示字符类 ^\/ 表示 非/的字符 +表示出现n次
第三个括号:(\/[^\?]*)? ^\? 不是 ? 的字符 * 表示出现0,1次,最后的?表示前面第三个括号里面的内容可以没有。

第四个括号:(\?[^#]*)? 首先是一个? ^#表示不是#的字符串
第五个括号:(#.*)?/; # 然后后面是任意字符
*/

var arr = url.match(reg); // 获取()中捕获的内容

var protocol = arr[1];
var host = arr[2];
var pathname = arr[3];
var search = arr[4];
var hash = arr[5];

str.replace 用正则替换一个数字

1
2
3
4
var str = 'The price of tomato is 5, the price of apple is 10.';
str.replace(/(\d+)/g, '$1.00';

// str -> 'The price of tomato is 5.00, the price of apple is 10.00.'

小案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var container = document.getElementById('container');

var html = '<label>网址:</label><input placeholder="以http://起始">';

html = html.replace(/[<>]/g, function(m0){

switch(m0){
case '<':
return '&lt;';
case '>':
return '&gt;';
}

});

container.innerHTML = html;

全局模式

/g 表示 全局模式, /i 表示不区分大小写

lastIndex表示下一次匹配的起始位置

如果将lastIndex 改变,则会改变下一次匹配的位置

1
2
3
4
5
6
7
8
9
10
11
var str = 'aabab';
// 贪婪匹配
var patt1 = /a.*b/g; // 它将会匹配最长的以 a 开始,以 b 结束的字符串
console.log(str.match(patt1)); // 输出 ["aabab", index: 0, input: "aabab"],匹配了整个字符串

// 懒惰匹配
var patt2 = /a.*?b/g; // 这里 *? 就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复
// patt2 将会匹配最短的,以 a 开始,以 b 结束的字符串
console.log(str.match(patt2)); // 输出 ["aab", "ab"]
// 为什么第一个匹配是 aab 而不直接是 ab 呢?
// 简单的说,正则表达式还有另一条规则,比 懒惰/贪婪 规则的优先级更高:最先开始的匹配拥有最高的优先权

JSON


JavaScript Object Notation

JSON.parse(text,[function])

Json -> JS

1
2
3
4
5
6
7
8
9
10
var userjson = '
{\
"id": 1,\
"nick": "春鸟秋虫",\
"avatar": "1.jpg",\
"tags": null,\
"authed": false \
}'

var user = JSON.parse(userJson);

第二个参数传入一个方法,会将key 跟 value 传入,便于转换之后进行一些操作:

1
2
3
4
5
6
var user = JSON.parse(userJson, function(k, v) {
if(k==='avatar') {
return 'http://music.163.com/img/' + v;
}
return v;
}

parse IE6/7 不支持的做法如下:

JSON.stringify(value,[replacer])

序列化,将JS->JSON

replacer数组表示 进行部分序列化,将想要序列化的属性传入。

文章作者: Ammar
文章链接: http://lizhaoloveit.cn/2016/08/03/JavaScript%E7%A8%8B%E5%BA%8F%E8%AE%BE%E8%AE%A1%E5%9F%BA%E7%A1%80%E7%AF%87/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Ammar's Blog
打赏
  • 微信
  • 支付宝

评论