1 声明变量
可以使用var 和let,由于javaScript存在变量提升,会把声明的变量全部提到头部。而使用let可以声明一个块级作用域的变量。
在函数里不使用var 或者let 则是全局变量,全局变量都属于window这个对象的,在页面关闭时被销毁
function f1(){
var x = 1 ;
if(true){
var x = 2;
}
alert(x) //结果为 2
}
function f1(){
let x = 1 ;
if(true){
let x = 2;
}
alert(x) //结果为1
}
2 数据类型
一个变量声明之后,可以任意改变数据类型
类型共有: stirng ,number, Boolean,object,function,null,undefined其中对象又有object,Date,Array。
每个变量都有construstor 这个属性,返回构造函数,从中可以看到是什么类型
输出: 使用反引号可以多行输出 ,如果不想用\n的话。
var name = `这是一个
多行
字符串`;
模板字符串:
var name = '小明';
var age = 20;
var message = `你好, ${name}, 你今年${age}岁了!`;
3 类型转换
任何类型转换为字符串: toString(),或者String(变量)
任何类型转化为数字 Number(变量); Boolean 类型的话:true 为0,false为1
typeof 得到类型,instanceof 可以判断摸个对象是否是某个类型
4 声明对象的方式
1) var person = { name :”小明”};
2) 适用对象构造器,
function person (name){ this.name = name};
var xiao = new person(name);
3) var person = new Object();
删除对象属性的方法: delete person.name;
判断一个对象是否有某个属性:'name' in person ,如果有返回true ,否则else;
5 正则表达式对象
/正则表达式主体/修饰符(可选)
test 方法,判断某个字符串是否符合正则表达式
exec 方法, 返回匹配结果,是字符串,没有返回null,一次只查找一个。
修饰符: i 大小写不敏感,g全局匹配,m执行多行匹配
string 的 replace,search方法
6 异常捕获
Js同样支持try catch
function message()
{
try {
adddlert("Welcome guest!");
} catch(e) {
alert(e)
}
}
7 变量提升和严格模式
js 允许我们先使用变量后声明,函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。但是初始化并不会。在非严格模式下,变量不声明,即是全局变量,也是可以用的
x= 7; alert(x) var x;
严格模式:在脚本或变量的头部加上 “use strict” ,将会有诸多限制。比如变量必须声明才能用。
8 误区
1) 赋值运算符应用错误:
var x = 0 ; if(x=10){} 此时不会报错,并且x 会被赋值为10,并且执行if里的代码
2) 比较运算:
if(“10” == 10) 为true,“===” 之比较值是否相等,而不比较类型是否相等
if(“10”===10) 为false “===” 为恒等运算符,比较类型和值全部相等
9 Javascript void
Javascripot:void(0)void操作符指定要计算一个表达式但是不返回值。
当然,函数还是要执行的。
<a href=”javascript: void(0)”>点我</a> 此时这个超链接并不会发生跳转,但是又有超链接的特性
10 for in
可以遍历对象中的属性
For(var x in person){console.log(person[x]) }
11 函数
在函数中,this代表调用此函数的对象。
函数中参数问题: 参数可以不匹配,javaScript 允许传入任意个参数。
arguments 只能在函数内部使用,并且永远指向当前函数调用者传递进来的所有参数。类型Array,但又不是Array。
如果想接受任意多个参数,可以使用 rest 参数。 function abs(...rest){} 类似与Java的不定参数。
12 String方法
indexOf()
lastIndexOf()
match()
replace()
search()
split()
substr()
substring()
toLowerCase()
toUpperCase()
13 Array 方法
concat();
push();
pop();
toString();
reverse();
sort();
14 Map与Set
Map是一个键值对类型,key值不能重复。初始化Map需要一个二维数组,或者直接初始化一个空Map。
var person = new Map([['name','小明']]);
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需要一个一维数组,或者是一个空的Set(),没有获取方法。需要用到迭代器。
var s1 = new Set(); // 空Set var s2 = new Set([1, 2, 3]); // 含1, 2, 3
s.add(4); // 含1, 2, 3,4
s.delete(3) // 含1, 2,4
15 迭代器(iterabel)
for.... of 只能用于数组,Map,Set ,for... in只能遍历对象(由于数组也是对象,所以for...in也可以用于遍历数组)
var a = ['A', 'B', 'C'];
var s = new Set(['A', 'B', 'C']);
var m = new Map([[1, 'x'], [2, 'y'], [3, 'z']]);
for (var x of a) { // 遍历Array
console.log(x);
}
for (var x of s) { // 遍历Set
console.log(x);
}
for (var x of m) { // 遍历Map
console.log(x[0] + '=' + x[1]);
}
15 析构赋值
可以使用析构赋值,直接对多个变量一起赋值。
var [x,y,z] = [2,3,4] // x =2 , y=3 , z =4
var person = {name : "小明", age : 10,address : '中国'};
var {name,age} = person // name ='小明' ,age = 10
应用:可以直接用来交换俩个变量的是,而无需中间变量 [x,y] = [y,x];
可以将函数的参数写成析构的形式,比较方便
function abs ({name,age,address}){
console.log(`${name}的年龄是${age},地址是${address}`);
}
abs({name:"小明", age: 10,address:"中国"}); //小明的年龄是10,地址是中国
//小明的年龄是10,地址是中国
15 特殊函数
apply 用来解决函数中this指向不明的问题,共有俩个参数,第一个是this的指向,第二个是参数数组。也可以用作装饰器,为函数新添加一些功能。如果没有this,传入null就可以了。
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
call函数和apply函数类似,但是不是将参数打包成数组,而是将参数按照顺序传入。
map函数可以把一个函数作用于数组的每项进行计算,这个函数需要一个参数。并返回结果数组。例如计算平方。map函数的参数是一个函数。
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(function(x){return x*x;}); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
reduce函数可以把一个函数作用于数组。这个函数必须接收两个参数,reduce()
把结果继续和序列的下一个元素做累积计算。例如实现求和:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
filter可以通过一个函数把数组中的元素过滤掉。函数返回true,保留,否则删除。这个可以有多个参数,第二个参数是当前索引,第三个参数是数组元素本身
例如,在一个Array中,删掉偶数,只保留奇数,可以这么写:
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
sort函数,可以对数组元素进行排序。默认排序方式是将元素全部转化为字符串利用ASCII进行排序。
[10, 20, 1, 2].sort(); // [1, 10, 2, 20] 默认排序,很明显与我们想要的不同。
var arr = [10, 20, 1, 2,11,12,13];
arr.sort(function(x,y){ 、、
if(x > y) return 1;
if(x ==y) return 0;
if(x<y) return -1;
})
15 闭包
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。相当于我们建立了一个指针,使他指向了函数中的局部变量。因此这个局部变量是常驻内存的。所以不可乱用闭包。
闭包是是一种通过全局变量访问局部变量的典型用法。例如下面的f2函数就实现了闭包,他访问f2函数里的变量,使得f3也可以访问f1的局部变量x。
function f1(){
var x = 1;
function f2(){
x ++;
alert(x);
}
return f2;
}
var f3 = f1(); //此时闭包函数f2还没有执行
f3(); //2 //此时才执行
f2(); //3
15 genetor(生成器)
像一个函数,但可以返回多次。定义 function*代表声明了一个generator, yield相当于return,只不过每次yield之后,就停止在哪里,等待下一次的yield;看上去就像一个可以记住执行状态的函数,可把我们的异步回调代码变成"同步代码",
function* abs(){
for(var i =1;i<100;i++){
yield i;
}
}
遍历方法:
for(var x of abs()){ //遍历generator的方式。
console.log(x);
}
或者使用这样的:
var f = abs(5);
f.next(); // {value: 1, done: false},放回的是一个键值对,value代表返回值,done代表generator是否结束。
15 Date对象
var now = new Date();
console.log(now); // Wed Jun 24 2015 19:49:22 GMT+0800 (CST)
console.log(now.getFullYear()); // 2015, 年份
console.log(now.getMonth()); // 5, 月份,注意月份范围是0~11,5表示六月
console.log(now.getDate()); // 24, 表示24号
console.log(now.getDay()); // 3, 表示星期三
console.log(now.getHours()); // 19, 24小时制
console.log(now.getMinutes()); // 49, 分钟
console.log(now.getSeconds()); // 22, 秒
console.log(now.getMilliseconds()); // 875, 毫秒数
console.log(now.getTime()); // 1435146562875, 以number形式表示的时间戳
Date对象的月份从0开始,0 = 1月
16 操作DOM
document是所有页面所有DOM元素的根节点。操作DOM 元素都是基于此的。
获取元素:
document.getElementById(); //单个
document.getElementsByClassName(); //数组
document.getElementsByTagName() //数组
document.getElementsByName() //数组
更新DOM元素:
var div1 =document.getElementById("div1");
div1.style.color = "red"; //更新style属性,但是使用的是驼峰命名法,如font-size 在这里应该写成div1.style.fonfSize
div1.innerHTML = '<p>你好</p>' //更新元素里的html
div1.innerText = '你好' //更新元素里的文本
div1.getAttribute('id') //获取id属性
div1.setAttribute('style','color : "red"' ) //设置属性
div1.removeAttribute('style') //移除属性
插入DOM元素:
var ele = document.createElement('p'); //创建一个新元素
ele.innerText = '哈哈哈';
div1.appendChild(ele); //插入元素,吧ele插入到div1元素里面,在最最后
div1.insertBefore(ele, referenceElement); //可以将ele插入referenceElement前面。referenceElement代表的是dvi1元素里的一个元素,
删除DOM元素
div1.removeChild(ele) //移除元素
16 Promise
在javascript中,所有代码都是单线程的。也就是说我们只能一个函数执行完再执行另外一个函数,类似于排队。但是偶尔也有特殊情况,异步执行就是一种特殊情况,可以直接插队,相当于人民币玩家,当函数的主体执行完毕后,回调函数就会插入到当前正在执行的进程中,开始执行。异步执行主要通过回调函数实现。所有的费时操作都可以必须异步执行。
setTimeout(function(){
console.log("回调函数执行"); //一秒钟之后才会执行
},1000)
console.log("我先执行") //可以看到这个先于回调函数执行。
但是这样方式的回调函数,如果有多层嵌套的话,想一想都恐怖。