1. 数据类型
数组
JavaScript的数组可以包括任意数据类型。例如:
var arr = [1, 2, 3.14, 'Hello', null, true];
另一种创建数组的方法是通过Array()函数实现:
new Array(1, 2, 3);
对象
JavaScript的对象是一组由键-值组成的无序集合,例如:
var person = {
name: 'Bob',
age: 20,
tags: ['js', 'web', 'mobile'],
city: 'Beijing',
zipcode: null
};
JavaScript对象的键都是字符串类型,值可以是任意数据类型。
JavaScript用一个{...}表示一个对象,键值对以xxx: xxx形式申明,用,隔开。
访问属性是通过.操作符完成的,但这要求属性名必须是一个有效的变量名。如果属性名包含特殊字符,就必须用''括起来:
var xiaohong = {
name: '小红',
'middle-school': 'No.1 Middle School'
};
xiaohong['middle-school']; // 'No.1 Middle School'
xiaohong['name']; // '小红'
xiaohong.name; // '小红'
由于JavaScript的对象是动态类型,你可以自由地给一个对象添加或删除属性:访问不存在的属性不报错,而是返回undefined
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
var xiaoming = {
name: '小明'
};
xiaoming.age; // undefined
xiaoming.age = 18; // 新增一个age属性
xiaoming.age; // 18
delete xiaoming.age; // 删除age属性
xiaoming.age; // undefined
delete xiaoming['name']; // 删除name属性
xiaoming.name; // undefined
delete xiaoming.school; // 删除一个不存在的school属性也不会报错
如果我们要检测xiaoming是否拥有某一属性,可以用in操作符,如果in判断一个属性存在,这个属性不一定是xiaoming的,它可能是xiaoming继承得到的:
'name' in xiaoming; // true
'grade' in xiaoming; // false
要判断一个属性是否是xiaoming自身拥有的,而不是继承得到的,可以用hasOwnProperty()方法:
var xiaoming = {
name: '小明'
};
xiaoming.hasOwnProperty('name'); // true
xiaoming.hasOwnProperty('toString'); // false
2. 条件判断
JavaScript把null、undefined、0、NaN和空字符串''视为false,其他值一概视为true,因此上述代码条件判断的结果是true。
3. map和set
map
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95
var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
set
Set和Map类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在Set中,没有重复的key。
var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
add(key)方法可以添加元素到Set中,可以重复添加,但不会有效果:
4. 函数
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
function指出这是一个函数定义;
abs是函数的名称;
(x)括号内列出函数的参数,多个参数以,分隔;
{ ... }之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined。
由于JavaScript的函数也是一个对象,上述定义的abs()函数实际上是一个函数对象
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
};
在这种方式下,function (x) { ... }是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs,所以,通过变量abs就可以调用该函数。
由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:
传入的参数比定义的少也没有问题:
abs(); // 返回NaN
要避免收到undefined,可以对参数进行检查:
function abs(x) {
if (typeof x !== 'number') {
throw 'Not a number';
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
arguments
javaScript还有一个免费赠送的关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array:
function abs() {
if (arguments.length === 0) {
return 0;
}
var x = arguments[0];
return x >= 0 ? x : -x;
}
abs(); // 0
abs(10); // 10
abs(-9); // 9
JavaScript的函数可以嵌套
5. 作用域
由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:
不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性:
'use strict';
var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // Learn JavaScript'
用let替代var可以申明一个块级作用域的变量:
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
i += 1; // SyntaxError
}
ES6标准引入了新的关键字const来定义常量,const与let都具有块级作用域:
const PI = 3.14;
PI = 3; // 某些浏览器不报错,但是无效果!
PI; // 3.14
6. 方法
在一个对象中绑定函数,称为这个对象的方法。
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
apply
虽然在一个独立的函数调用中,根据是否是strict模式,this指向undefined或window,不过,我们还是可以控制this的指向的!
要指定函数的this指向哪个对象,可以用函数本身的apply方法,它接收两个参数,第一个参数就是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。
另一个与apply()类似的方法是call(),唯一区别是:
apply()把参数打包成Array再传入;
call()把参数按顺序传入。
比如调用Math.max(3, 5, 4),分别用apply()和call()实现如下:
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5
装饰器
JavaScript的所有对象都是动态的,即使内置的函数,我们也可以重新指向新的函数。
var count = 0;
var oldParseInt = parseInt; // 保存原函数
window.parseInt = function () {
count += 1;
return oldParseInt.apply(null, arguments); // 调用原函数
};
// 测试:
parseInt('10');
parseInt('20');
parseInt('30');
count; // 3
7. 高阶函数
我的理解是类似于C++中的函数指针
数组自带map/reduce方法,参数为函数对象,还有filter,sort
sort()方法会直接对Array进行修改,它返回的结果仍是当前Array
filter也是一个常用的操作,它用于把Array的某些元素过滤掉,然后返回剩下的元素。Array的filter()也接收一个函数。和map()不同的是,
filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
例如:
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
arr.filter(function (x) {
return x % 2 !== 0;
});
8. 闭包(重难点)
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
9. 箭头函数的使用
10. 正则表达式
d //匹配一个数字
w //匹配一个字符或者数字
ex:
'00d'可以匹配'007',但无法匹配'00A';
'ddd'可以匹配'010';
'ww'可以匹配'js';
. //匹配任意字符
ex:
'js.'可以匹配'jsp'、'jss'、'js!'
要匹配变长的字符,在正则表达式中,用*表示任意个字符(包括0个),
用+表示至少一个字符,用?表示0个或1个字符,用{n}表示n个字符,用{n,m}表示n-m个字符:
ex:
d{3}s+d{3,8}。
我们来从左到右解读一下:
d{3}表示匹配3个数字,例如'010';
s可以匹配一个空格(也包括Tab等空白符),所以s+表示至少有一个空格,例如匹配' ',' '等;
d{3,8}表示3-8个数字,例如'1234567'。
精确匹配
ex:
[0-9a-zA-Z\_]可以匹配一个数字、字母或者下划线;
[0-9a-zA-Z\_]+可以匹配至少由一个数字、字母或者下划线组成的字符串,比如'a100','0_Z','js2015'等等;
[a-zA-Z\_$][0-9a-zA-Z\_$]*可以匹配由字母或下划线、$开头,后接任意个由一个数字、字母或者下划线、$组成的字符串,也就是JavaScript允许的变量名;
[a-zA-Z\_$][0-9a-zA-Z\_$]{0, 19}更精确地限制了变量的长度是1-20个字符(前面1个字符+后面最多19个字符)。
A|B可以匹配A或B,所以[J|j]ava[S|s]cript可以匹配'JavaScript'、'Javascript'、'javaScript'或者'javascript'。
^表示行的开头,^d表示必须以数字开头。
$表示行的结束,d$表示必须以数字结束。
11. 又一个难点,原型链继承
12. 全局变量与局部变量
定义在函数外面的变量一定是全局变量,定义在函数内部的变量如果声明了var则是局部变量,没有声明var
则是全局变量。
例如:
var age = 21;//全局变量
function test()
{
var local = "vbscript";//局部变量
name = "zhuminjie"; //全局变量
}
13. with语句
with语句:(对象操作的语句)
功能:为一般的程序建立默认的对象
格式:
with(<对象>)
{
<语句组>
}
例如:
with(document)
{
write("<li>hello</li>");
write("<li>world</li>");
write("<li>hello world</li>");
}
14. for...in语句:重复执行指定对象的所有属性
格式:
for(变量in对象)
{
<语句组>
}
15. 默认对象
日期对象
var date = new Date();//加不加括号一样
数组对象
var fruit = new Array("苹果","鸭梨","橙子");//定义数组
var sports = ["篮球","足球","羽毛球"];//定义数组,推荐使用这种方式
var cities = new Array();
cities.push("武汉");
cities.push("深圳");
cities.push("厦门");
for(var i = 0;i < fruit.length;i++)
{
document.writeln("fruit["+i+"]"+":"+fruit[i]+"<br>");
}
for(var i = 0;i < sports.length;i++)
{
document.writeln(sports[i]+"<br>");
}
for(var i in cities)
{
document.writeln(cities[i]+"<br>");
}
数组对象的常用方法
join([分隔符]) 数组元素组合为字符串
toString()以字符串表示数组
reverse()数组反转
valueOf()返回数组值
二维数组
var a = new Array(3);
a[0] = new Array[2];
a[1] = new Array[4];
a[2] = new Array[3];
for(var i = 0;i < a.length;i++)
{
for(var j = 0;j < a[i].length;j++)
{
document.writeln(a[i][j]);
}
}
16. 对象定义
构造函数定义对象类型
实例化对象
例如:
function member(name,gender) //构造函数定义对象
{
this.name = name;
this.gender = gender;
this.display = display; //指定member对象的display方法
}
member.prototype.sex = "m"; //原型的方式
function display()
{//这里this和java中不一样,display函数还可以绑定给其他对象,绑定了谁this就代表谁
var str = this.name+":"+this.gender;
document.writeln(str+"<br>");
}
var m1 = new member("zhongcunmu","m");//实例化对象
var m2 = new member("shezili","m");
var m3 = new member("fenghuiting","f");
with(document)
{
writeln(m1.name+":"+m1.gender+"<br>");
writeln(m2.name+":"+m2.gender+"<br>");
writeln(m3.name+":"+m3.gender+"<br>");
}
17. 计时器
setTimeout("alert('执行成功')",7000); //第一个参数为要执行的js语句或者函数,第二个为计时的毫秒时间
setInterval():
格式
[定时器对象名=]setInterval("<表达式>",毫秒)
功能:
重复执行表达式直至窗口、框架被关闭或者执行clearInterval
clearInterval():终止定时器
格式:
clearInterval(定时器对象名)
例如:
var sec = 0;
var timeId = setInterval("count()",1000);
function stopCount()
{
clearInterval(timeId);
}
18. js内置对象
window 窗口对象
screen 屏幕对象
event 事件对象
location 位置对象
alert()函数 模态
confirm()非模态
document.links //获取页面内所有的链接存在在links数组中
location.href=“http://www.baidu.com” //可以使用这种方式重转向
document.getElementById("num1").innerHTML = "sA"; //改变某一标签内的内容
19. 绑定事件
js中为某个对象(控件)绑定事件通常可以才去两种手段
1)<input type="button onclick="clickHandler">
2)<input type="button id="btn1">
<script type="text/javascript">
var v= document.getElementById("btn1");
var v.onclick = clickHandler;
</script>
20. 函数
js中函数就是对象
js中函数没有方法(函数)重载的概念
js中有个Function对象,所有自定义的函数都是Function对象类型的
Function对象接受的所有参数都是字符串类型的,其中最后一个参数就是函数要执行的执行体
前面的参数都是函数真正需要的参数。
下面定义函数的方法效果是一样的
function add(number)
{
alert(number+20);
}
var add = new Function("number“,"alert(number+20)");//最后一个参数必须是函数体内容
var add = function(number)
{
alert(number+20);
}
js中每个函数都有一个隐含的对象arguments,表示函数实际传递的参数,这里有点特别,就是你定义的时候
不一定有参数,但是你调用的时候传了参数也可以获取的。每个函数都有个length属性,表示期望接收的
参数个数。
function add(name1,name2)
{
alert(arguments[0]); //即name1
alert(arguments[1]);
}
add(1,2,3); //在函数里面可以通过arguments获得第三个参数
js中如果函数没有声明返回值则返回undefined
21. js中5种原始数据类型
Undefined、Null、Boolean、Number、String
Undefined数据类型的值只有一个:undefined
Null类型的值只有一个:null
Boolean类型的值只有两个:true,false
null实际上是从undefined派生过来的
typeof是一元运算符,后跟变量名称,用于获取变量的数据类型,返回值有五个boolean,number,string,object
22. 强制类型转换
js中三种:Boolean(value),Number(value),String(value)
23. js中所有对象都是从object派生过来的,object的属性是不可以枚举的,其他的是可以的
object.propertyIsEnumberable("prototype") //判断属性不是不是可枚举的
24. js中定义对象的几种方式(js中没有类的概念,只有对象)
js中定义对象的最常见方式
1)基于已有的对象扩充其属性和方法
2)工厂方式创建对象
3)使用原型+构造函数方法定义对象
4)构造函数的方式
5)原型的方式
6)动态原型方式
var ob = {username:"zhu",password:"123"};
alert(ob.username);
function createObject()
{
var ob = new Object();
object.name = "zz";
object.password = "123";
return ob;
}
var ob1 = createObject();
js中定义属性的两种方式
例子:
var ob = new object();
alert(object.username);
object.name = "zcm"; //一种
object["name"] = "zhu"; //另一种
删除属性
delete objext.name;
25. 数组
两种定义方式
var a = new Array();
var b = [1,2,3];
b.sort(); //数组有排序函数,数组的sort方法默认将待排序内容转换为字符串,然后按照字符串的先后顺序排序,也可以自定义排序的规则
26 js中的继承
1)对象冒充
function parent(username)
{
this username = username;
}
function child(username,password)
{
this.method = parent;
this.method(username);
delete this.method; //关键在于理解js中this
this.password = password;
}
2) call方法方式
call方法是Function对象中的方法,因此我们定义的每个函数都有该方法,可以通过函数名来调用
call方法,call方法的第一个参数会被传递给函数中的this,从第二个函数开始,逐一赋值给函数中的参数
function test(str)
{
alert(this.name+"zz");
}
var ob = new Object();
ob.name = "zs";
test.call(ob,"fdfdf"); //test.call相当于调用了call函数。 将ob付给了this
function Parent(username)
{
this.username = username;
this.sayHello = function()
{
alert(this.username);
}
}
function child(username,password)
{
Parent.call(this,username);
this.password = password;
this.sayWorld = function()
{
alert(this.password);
}
}
var pa = new Parent(" zhang");
var ch = new child("lili","123");
pa.sayHello();
ch.sayHello();
ch.sayWorld();
3)apply方法方式
与call不同的地方
function child(username,password)
{
Parent.apply(this,new Array(username)); //apply是将多个属性以数组的形式传进去,call是离散的方式
}
4)原型链方式
function Parent2()
arent2.prototype.hello = "hello";
arent2.prototype.sayHello = function()
alert(this.hello);
unction Child2()
Child2.prototype = new Parent2();
Child2.prototype.world = "world";
Child2.prototype.sayWorld = function()
{
alert(this.world);
}
var ch2 = new Child2("zzz","888");
ch2.sayHello();
ch2.sayWorld();
5)混合方式(推荐方式)