1.数据类型
①数值类型(number):123,10e10;
合法的数值范围:2;
十六进制:OX表示;
1e2=100=1x10x10;
最大值:Number.MAX_VALUE//某些浏览器是可以超过这个值的;
NaN:not a number;//非数字值是数字类型。
NaN === NaN//为false;//三个等号比较类型和值;
②布尔类型(bolean):true,false;
③字符串类型(string):‘dags2’;tostring()将其他类型转换成字符串;
var a = “sss"sssss”,//转义符:"=>";
④未定义类型(undifined):undifined;var m/m就是undefined;
当声明了一个变量但是没有赋值则为undefined;函数没有返回值的时候;
⑤null类型(本质上是一个特殊的object,object类型的一个值);表示空对象。对象类型的一个值;
//null == undefined 为 true; null === undefined 为false因为数值类型不一样;
⑥object类型(引用类型);
⑦function类型(函数类型);
⑧获取变量的数据类型:typeof();
2.运算符
①如果一个操作数是NaN则结果是NaN;
②333*'sss’得NaN;
③222*'99’会先把’99’转换成99再进行相乘;
④Infinity0 =>NaN;Infinity非零数值得Infinity或-Infinity取决于有符号数的操作符号;
⑤Infinity*Infinity =>Infinity;
⑥Infinity/Infinity=>NaN;
⑦0%任何数得0;Infinity % 0 = NaN;等
自增自减运算符:a = 1;++a后 a = 2,++a = 2;a++后 a = 2,a++ =1;
⑧条件运算符:语法:表达式1?表达式2:表达式3;1true返回2,false返回3;
3.运算符的优先级
第一级:();
第二级:a++,b–;
第三极:逻辑!,一元±,typeof;
第四级:* / %
第五级:二元±;
第六级:< > >= <=;
第七级:&& ||;
第八级:? : 条件运算符;
第九级:赋值运算符 = += *= -= /= %=;
第十级:逗号;
练习:
①var a = ‘1’,b = 3, c=true;
求下面的值:a>b:false;
a>=c:false,因为a转化为数字1,而c的f的ascii值为90+,所以c>a;
!b:flase;!!(b):将b转换成boolen类型;
a+b :‘13’//优先字符串操作;b+c:4;//true转化成1;
b-a:2;b&&a:true;!(a||b):false;
②:var a = ‘1’,b=‘3’,c=‘true’;
求:a>b&&c<a:false;
+c:1;
++a+c:3;
++b+‘sss’:4sss;
6/0:infinity;
NaN*0:NaN;//只要有NaN的都是NaN;
b>c?++a:c 得2;
4.显示类型的转换
转换为数值类型:Number(mix)//undefined返回NaN;
ParseInt(string,radix)//转换成整数;
parseFloat(String)//转换为字符串类型: String(mix);//a+" " == string(a);
Boolean(mix)//false,’’ ‘’ ,0,NaN,null,undefined,其余任何值都转换成true;
两次取反跟Boolean方法效果一致;var a = 3,b = 0,c = " ";
!!a:true;!!b:false;!!c:false;
5.隐式类型的转换:
就是当表达式进行运算时,如果类型不一致,JS引擎会自动根据规则把类型进行转换再进行运输.
6.循环分支语句
①if语句:
Math.random():随机返回0–1之间的小数;若想要得到一个随机数则可以:parseInt(Math.random()*10)//转换成整数;
//如果是字符串将其转化成数值类型并返回结果,否则直接把变量转化成boolean类型输出:
var t = '1sss'; if(typeof(t) == "string"){ console.log(Number(t)); }else{ console.log(!!t) }
②while语句;
//计算1-100的和;
```javascript
var n = 0;
var i = 1; // 循环的索引
while(i<=100){
n += i;
i++;
}
//输出10个(0--100)间的随机数
var t ;
var i = 0;
while(i<10){
t = parseInt(Math.random()*100);
console.log(t);
i++;
}
//实现1-10的阶乘
var m = 1;//阶乘的索引
var result = 1;//阶乘的结果
while(m<10){
result *= m;
m++
}
console.log(result);
③for循环
//输出十个0--100随机数
for(var i = 0;i<=10;i++){
console.log(Math.random()*100);
}
④for each:
let arr = [‘a’,‘b’,‘c’,‘d’]
arr.forEach(function(val,idx,arr){
console.log(val+’,index’+idx)//val是当前元素,index当前元素索引,arr数组
console.log(arr)
})a
⑤for in
伪循环enumerable对象而设计的;
可枚举性(enumerable)用来控制所描述的属性,(是否可以被遍历出来)是否将被包括在for…in循环之中。具体来说,如果一个属性的enumerable为false,下面三个操作不会取到该属性。
- for…in循环
- Object.keys方法
- JSON.stringify方法
let obj = {a:'1',b:'2',c:'3',d:'4'}
for(let o in obj){
// console.log(o);//遍历实际上是对象的属性名称abcd
console.log(obj[o]);//属性对应的值1,2,3,4
}
//for in
var t = {};
t.name = '123';
t.age = 19;
t.run = function(){
console.log('ss');
}
for(var k in t){
//k相当于属性的名字的变量
//第一次循环k相当于t变量的第一个属性名,以此类推;
console.log(k);
if(typeof(t[k]) == 'number'){
console.log(t[k]);
}
}
⑥for…of
let arr = ['china','america','korea']
for(let o of arr){
console.log(o)//china,america,korea;
}
不能循环一个普通对象,但可以循环一个拥有enumerable属性的对象;
按照对象拥有的属性进行循环,可以用内置的Object.values()方法;
let obj = {a: '1',b: '2',c:'3',d:'4' }
for(let o of Object.keys(obj)){
console.log(o)//a,b,c,d
}
如果我们按照对象所拥有的属性值进行循环,使用内置的Object.values()方法;
let obj = {a:'1',b:'2',c:'3',d:'4'}
for(let o of Object.values(obj)){
console.log(o);//1,2,3,4
}
//循环一个字符串
let str = 'love'
for(let o of str){
console.log(o)//l,o,v,e
}
//循环一个map
let iterable = new Map([["a",1],["b",2],["c",3]]);
for(let [key,value] of iterable){
console.log(value);//1 2 3
}
for(let entry of iterable){
console.log(entry);
}
//[a,1] [a,2] [c,3]
⑦with语句
7.创建对象
//对象字面量
var t = {
age:19,
run:function(){
console.log('嗯');
}
};
t.color = 'yellow';
console.log(t.age);
t.run();
△进程之间是相互隔离的,不相互影响,有些特殊情况可以进行相互干预;
线程是执行代码的最小单位,我们所有的代码都在线程里面执行;
线程的内存分为:栈内存(放简单数据类型、/数值类型,布尔类型,undefined),堆内存(对象类型,string是一个特殊引用类型)
;
8.构造函数及其原型
object原型属性和方法:
原型属性:toString();//转换成字符串;
toLocalString();//转化成本地化对应的字符串;
ValueOf();//获取他的值;
hasOwnProperty();//判断属性是否是自己添加的;
方法:
var cat = {
color:'red',
weight:20,
name:'karry',
ID:23,
run:function(){
console.log(this.name + '奔跑方法');
},
jump:function(){
}
};
//跑步方法的调用
cat.run();
//输出猫所有子定义属性;
for(var k in cat){
console.log(k);
}
//数学对象封装
var myMath = {
PI:3.1415926,
sum:function(n){
var result = 0;
//实现1--n的和
for(var i = 0;i<=n;i++){
result += i;
}
return result;
},
fatorial: function(n){
//求1--n的阶乘
var result = 1;
for(var i = 1;i<=n;i++){
result *= i;
}
return result;
}
};
console.log(myMath.PI);
console.log(myMath.sum(100));
console.log(myMath.fatorial(10));
9.Array类型
var arr = [1,2,4,"fd"];
console.log('length ='+ arr.length);
//遍历
for(var i = 0;i<arr.length;i++){
console.log(arr[i]);
}
for(var k in arr){
console.log(arr[k]);
}
注意:从原型上继承来的属性也会被for in遍历,所以如果需要去掉这一部分属性,可以通过hasOwnProperty()进行过滤;
for(var k in t){
if(t.hasOwnProperty(k)){
console.log(k);
}
}
//或者
for(var k in t){
if(!t.hasOwnProperty(k)){
continue;
}
console.log(k);
}
//要求此函数接收两个参数,要求返回值为负数,0,正数,
//如果范回负数代表第一个参数小于第二个参数,0为相等,正则大于;
var compareFun = function (a,b){
return a-b;
};
var m = [3,20,10,9,11,12];
console.log(m);
// m.sort();
// console.log(m);
// m.sort(compareFun);
// console.log(m);
//由于匿名函数只用一次,没有必要创建一个变量,直接可以把匿名函数的表达式,、
//传递到sort函数里就行;
m.sort(function(a,b){
return a-b;
});
console.log(m);
10数组的方法-连接方法
①concat();连接原数组和传递参数形成一个新数组并返回,不影响原来的数组;如果传入的参数是数组,会把数组中的元素跟原数组的元素进行合并成一新数组;
var t = [1,2,3];
//调用数组的连接方法
var arr = t.concat('ss',true,222);
console.log(t);
console.log(arr);
var arr1 = t.concat('luoma','beijing',000);
console.log (arr1);
//结果
demo.js:4 (3) [1, 2, 3]
demo.js:5 (6) [1, 2, 3, "ss", true, 222]
demo.js:7 (6) [1, 2, 3, "luoma", "beijing", 0]
②join();
javascript
var t = [1,2,3];
//转换成字符串,用,隔开
console.log(t.toString());
//join也可以转换成字符串
console.log(t.join());
// join方法可以传递一个参数;用来分割数组中的元素;
console.log(t.join('-'));
console.log(t.join('+'));
//结果
demo.js:3 1,2,3
demo.js:5 1,2,3
demo.js:7 1-2-3
demo.js:8 1+2+3
9.数组的方法-切片方法
①slice:截取数组的一个片段或子数组,接受一到两个参数截取数组起始索引结束索引;
var t = [0,1,2,3,4,5];
console.log(t);
//slice复制数组的一部分;
//传一个参数的时候,是从参数的索引位置开始截取到数组的最后;
var a1 = t.slice(2);
console.log("a1 = "+a1);
// 传两个参数,从第一个参数索引开始第二个索引结束;
var a2 = t.slice(2,4);
console.log("a2="+a2);
//如果传递的是负数,从结尾开始计算一般不要用;
//只能往后截取,如果往前截取返回空数组;
var a3 = t.slice(-3,-1);
console.log("a3 ="+a3);
//结果
demo.js:2 (6) [0, 1, 2, 3, 4, 5]
demo.js:6 a1 = 2,3,4,5
demo.js:9 a2=2,3
demo.js:13 a3 =3,4
②splice();在原数组上进行插入或者删除,返回的结果是删除的元素或者数组;
// 对原数组有影响
var arr = [0,1,2,3,4,5,6];
var a1 = arr.splice(3);
console.log(arr);
console.log(a1);
// 两个参数;第一个是删除的起始索引,第二个是删除的
var a2 = arr.splice(3,1);
console.log(arr);//[0,1,2,4,5,6]
console.log(a2);//[3]
// 传递 两个以上的参数,第一个开始,第二个删除数据的个数,
// 第三个及后面的要插入start索引后面的参数;
var a3 = arr.splice(3,2,'ss','fd');
console.log(a3);
console.log(arr);
//demo.js:13 (2) [3, 4]
// demo.js:14 (7) [0, 1, 2, "ss", "fd", 5, 6]
// splice给数组任意元素插入数据;
arr.splice(3,0,'a');
console.log(arr);
// 替换元素
arr.splice(3,1,'q');
console.log(arr);
③数组案例
// 将数组内容进行反序
var t = [12,32,425,235,33,5];
console.log(t);
//js提供的reverse方法
// t.reverse();
// console.log(t);
// 用循环做
// var arr = new Array(t.length);
// 倒着遍历数组
// for(var i = t.length-1,k=0;i>=0;i--,k++){
// arr[k] = t[i];
// }
// console.log(arr);
// 优化上述
// for(var i = 0;i<t.length;i++){
// arr[t.length-i-1] = t[i];//直接把元数组中数据赋值给新数组对应位置
// }
// console.log(arr);
//第三种方法,不增加数组的情况下,直接修改
for(var i = 0;i<t.length/2;i++){
var temp = t[i];
t[i] = t[t.length-1-i];
t[t.length-1-i] = temp;
}
console.log(t);
// 求数组的最小值和其索引练习;
var t = [12,44,3,56,76];
var min,minIndex;
min = t[0];
minIndex = 0;
//循环数组中的每个值比较
for(var i = 0;i<t.length;i++){
if(t[i]<min){
min = t[i];
minIndex = i;
}
}
console.log(min);
console.log(minIndex);
// 求数组中数据的平均值,和
var t = [1,23,56,44,2];
var sum = 0,average = 0;
for(var i = 0;i<t.length;i++){
sum += t[i];
}
console.log('和是'+sum);
console.log('平均值'+sum/t.length);
// 对数组的数据进行排序
var t = [2,44,34,54,66,765];
console.log(t);
t.sort(function(a,b){
return b - a;
});
console.log(t);
// 给定一个数组去掉重复数据
var t = [11,23,435,54,22,11,22,23];
console.log(t);
var arr = [];
// 把原数组中的第一个数组插入到数组中
arr.push(t[0]);
// 判断并插入;
for(var i = 1;i<t.length;i++){ //遍历原数组
// if(arr.indexOf(t[i] == -1)){//indexof(),存在返回索引,不存在返回-1;
// arr.push(t[i]);//不支持IE8;
// }
//遍历新数组,看当前t[i],是否在新数组中;
for(var k = 0;k<arr.length;k++){
if(t[i] === arr[k]){
//如果相等已经存在不能插;
break;
}
}
if(k === arr.length){//判断循环是否到最后到最后;
arr.push(t[i]);
}
}
console.log(arr);
// 给定一个数组去掉重复数据 哈希对象属性去重
var t = [11,23,435,54,22,11,22,23];
console.log(t);
var h = {};
for(var k in t){
var str = t[k].toString();//把数组中的元素赋值给str;
h[str] = t[k];//把数组中的元素值设置给对象的属性,并且给属性值赋值;
//利用对象的属性不能重复;如果重复定义后面的会覆盖;
}
var arr = [];
for(var m in h){
arr.push(h[m]);
}
console.log(arr);
11.js事件循环机制
js单线程:执行线程和UI线程互斥。
同步任务:一般的赋值操作,循环,分支语句等;
异步任务:DOM事件,Ajax,BOM的一些api等;
时间循环机制:js执行引擎的主线程从任务队列中获取任务执行;
如果任务是异步任务,运行到异步任务时,异步任务会退出主线程,主线程进行下一个任务的获取处理;
如果异步任务完成
js代码是队列的形式一个一个执行的,同一时间只能执行一段代码;
12.执行上下文
栈的数据结构:先进后出;
1️⃣EC:函数执行环境(执行上下文);
2️⃣ESC:执行环境栈;
3️⃣VO变量对象:js的执行上下文中都有个对象用来存放执行上下文中可被访问但是不能被delete的函数标识符,形参,变量声明等。他们会被挂在这个对象上,对象的属性对应他们的名字,对象属性的值对应他们的值但实际上是不可能在js环境中访问到的活动对象;
4️⃣AO激活对象:有了变量对象存每个上下文中的东西,每进入到一个执行上下文时,这个执行上下文中的变量对象就被激活,该上下文中的函数标识符,形参没声明变量就可以被访问到了;
5️⃣scope chain:作用域链;
6️⃣执行上下文的生命周期:创建 执行 出栈等待销毁
创建阶段:创建作用域链(Scope Chain)
创建变量对象(或者AO):初始化函数的参数arguments,初始化函数声明 初始化变量。函数的优先级高于变量;
指定this对象:
执行阶段:变量赋值 代码执行
7️⃣js的执行分为:解释 执行 两个阶段;
解释阶段:分析,作用于规则确定;
执行阶段:创建执行上下文,执行函数代码,垃圾回收;
8️⃣函数变量的作用域:js没有块级作用域:只有函数作用于和全局作用域,子可以访问父;
9️⃣作用域链:是一个数组;有序访问js内部;当前函数的作用域链在最前端而全局在最后端;
变量的搜多从作用域链最前端向最后端搜索,直到全局作用域,标识符的解析是沿着作用域链一级一级都搜索的过程,从第一个对象开始逐级向后回溯,直到找到同名标识符为止,找到后不在继续遍历,找不到报错;
🔟函数的四种调用模式:
①方法调用模式:
// 定义按钮类,要求按钮类的构造函数可以接收参数初始化按钮的宽度,暗度,坐标x,y;
function Btn(width,height,x,y){
// 构造函数内部初始化
this.width = width;
this.height = height;
this.px = x;
this.py = y;
}
var b = new Btn(1000,100,2,3);
// 借用Math的min方法实现求数组【2,9,44】中的最小值
// var m = Math.min(2,33,4);
// console.log(m);
var m = Math.min.apply(null,[2,8,33]);
console.log(m);
// 把类数组转化成真正的数组
var t = {};//类数组,跟数组相似但不是数组;
t[0] = 1;
t[1] = true;
t[2] = 'jj';
t.length = 2;
var k = Array.prototype.slice.call(t,0);
console.log(k);
// 求1--100的和
var sum = 0,
n = 100;
// for(var i = 1;i<=n;i++){
// sum+=i;
// }
// console.log(sum);
// 递归
function sumN(num){
// 递归一定要有结束自己调用自己的出口;
// 函数调用自己;
if(num <=1){
return num;ß
}
return sumN(num-1)+num;
// return arguments.callee(num-1) + num;严格模式下会报错不要用
}
console.log(sumN(100));
//
// 求1--100的和
var sum = 0,
n = 100;
// for(var i = 1;i<=n;i++){
// sum+=i;
// }
// console.log(sum);
// 递归
function sumN(num){
// 递归一定要有结束自己调用自己的出口;
// 函数调用自己;
if(num <=1){
return num;ß
}
return sumN(num-1)+num;
// return arguments.callee(num-1) + num;严格模式下会报错不要用
}
console.log(sumN(100));
//
// 斐波那契数列递归实现
function fibonaqie(n){
if(n == 1){
return 1;
}
if(n == 0){
return 0;
}
return fibonaqie(n-1) + fibonaqie(n-2);
}
console.log(fibonaqie(5));
// 函数式编程
// Array.prototype.sort对数组中的元素进行排序,按照字符串大小排序
var t = [48,2,3,4,55,9,8];
console.log(t);
t.sort(function(a,b){//函数式编程
return a-b;
});
console.log(t);
// map方法,返回新数组,回调三个参数:当前项,索引,操作的数组
var t = [11,22,21,43,11];
// for(var i in t){
// console.log(t[i]);
// }
// 对数组中每个元素都进行*2,打印结果数组;
var m = t.map(function(item,index,array){
return item *2;
});
console.log(t);
console.log(m);
// forEach
var m = ['22',true,22];
// 打印m中的每个元素;
m.forEach(function(item,index){
console.log('index:'+index+' '+item);
});
13.垃圾回收机制
标记清除,被标记离开环境的变量在下一次回收启动的时候会被释放掉占用的内存空间:从根对象开始遍历所有可访问的对象,回收已不可访问的对象;
var a = [1,2,33,22,2,4];
a.forEach(function(item){
console.log(item);
});
// 数组清零,让gc尽快回收数组a的内存空间
a.length = 0;
// 对象复用
var t ={};
for(var i = 0;i<10;i++){
t.age = 19;
t.name = '1';
t.index = i;
console.log(t);
}
t.null;//对象如果已经不用了立即设为null;
13.原型链与闭包
所有对象都是基于原型上进行创建的,函数都有prototype属性指向函数的原型对象,根函数除外,都有_proto_属性;
所有函数的(对象实例)内部原型对象_proto_都会指向object.prototype(除过function)然后指向null;
构造函数的内部原型_proto_指向Function.prototype(所有函数的根)所有函数也是object对象的实例;
(Function.prototype.proto===object.prototype)所有函数也都是对象;
闭包(Closures):引用了自由变量的函数/闭包由函数和函数所声明的词法环境的集合
js中任何一个函数都是闭包;
// 工厂模式
// 创建10个cat每个对象都有年龄姓名表 属性方法
function createCat(age,name){//工厂模式标准化生成默认对象函数
var o = new Object();
o.age = age;
o.name = name;
o.run = function(){
console.log(o.name+'runing');
};
return o;
}
var c = createCat(19,'aassd');
c.run();
//
// 优点:进行批量创建都有公共默认值和属性对象
// 缺点:对象的方法不能跟其他对象共享,多占用内存;
// 不能识别对象的原型及构造函数;
// instanceof Cat;//false;
// 构造函数创建对象模式
function Cat(age,name){
this.age = age;
this.name = name;
this.run = function(){
console.log(this.name+'runing');
}
}
var c1 = new Cat(19,'ss');
c1.age = 88;//修改构造函数属性值
c1.run();
// 当使用new来调用构造函数时
// 1.创建一个空对象;
// 2.把空对象赋值给this;
// 3.执行构造函数里面的代码,this属性赋值初始化;
// 4.把新创建的对象返回;(如果有返回值,返回值是简单类型会直接忽略,还是返回this,
// 如果是引用类型直接返回引用对象)
//优点:可以使用instance追溯对象的原型及构造函数
//c1 instanceof Cat;//true
//c1.constructor === Cat
// 原型构建对象
function Cat(){
this.age = 19;
}
// 如果需要共享的方法和属性一般放到原型中定义
Cat.prototype.run = function(){
console.log(this.name,this.age);
};
Cat.prototype.name = 'black';//所有新对象共享
var c1 = new Cat();
var c2 = new Cat();
console.log(c1.name);
console.log(c2.name);
c1.run();
c2.run();
c1.name = 'good cat';
// 对象属性分为:读取和设置两种模式
// 如果读取,自己没有设置这个属性,就去原型上找,直到找到位置,找不到返回undefined;
// 如果是写入,自己没有这个属性,直接添加一个属性;
console.log(c1.name,c2.name);
// 原型继承模式
function Animal(age,name){
this.age = age;
this.name = name;
}
Animal.prototype.run = function(){
console.log(this.name + 'running...');
}
function Cat(age,name){
this.age = age;
this.name = name;
}
// 原型继承
// Cat.prototype.constructor === Cat
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;//
var c = new Cat(19,'ss');
c.run();//从aimal对象上继承的方法;
// 原型继承问题
// 子类构造函数的参数,没法传递给父类构造函数;
// 子类的原型constructor会被改变需要自己变回来;
// 父类中有引用类型的属性所有子类会共享这个引用类型;
// 组合继承模式
// 组合的原型继承和借用构造函数继承
// 父类
function Animal(age,name){
this.age = age;
this.name = name;
this.foods = ['水','苹果'];
}
// 在父类的原型上创建一个run方法;
Animal.prototype.run = function(){
console.log(this.name+'running');
};
// 定义子类
function Cat(age,name){
// 第一次执行父类构造函数
Animal.call(this,age,name);//借用父类构造函数给子类创建实例属性
}
// 第二次执行父类构造函数
Cat.prototype = new Animal();//组合原型继承模式;
Cat.prototype.constructor = cat;
var c = new Cat(19,'deail');
// 原型式继承
// 借用对象来构造另一个对象;
// 缺点:原型对象上引用类型的属性会造成子类对象进行共享;
function object(o){
function F(){
}
F.prototype = o;//空函数的原型指向o对象;
return new F();//创建一个f实例,f的内部原型指向o对象
}
var m = {age = 19,name:'jign',friends:['ss','dd']};
var m1 = object(m);
console.log(m1.friends);
// 寄生继承模式
function object(){
function F(){
}
F.prototype = o;
return new F();
}
// 传一个对象到方法内部,根据传来的对象构造新对象,并对新对象进行扩展增强
// 最后返回新对象
function createPersion(p){
var o = object(p);//构造一个新对象o
o.say = function(){//对新否造出来的对象进行扩展
console.log('hi');
}
return o;
}
// 寄生组合继承模式
// 组合了寄生继承模式和借用构造函数继承模式
// 父类
function Animal(age,name){
this.age = age;
this.name = name;
this.foods = ['水果','kk'];
}
Animal.prototype.run = function(){
console.log(this.name + 'runing');
}
function Cat(age,name){
// 使用构造函数继承模式来构建对象的实例属性
Animal.call(this,age,name);
}
// 寄生继承方法
Cat.prototype = inheritFrom(Animal.prototype);
var c = new Cat(19,'dd');
c.run();
// 寄生继承
function inheritFrom(o){
var t = Object(o);
t.constructor = Cat;//把cat原型的构造函数指回Cat构造函数
return t;
}
**14.正则表达式**
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
var str = '12,34,56';
var exp = /\d{2}/g;
var temp;
// exec方法:如果没有匹配项那么就会返回null
// 如果有匹配项会返回一个数组;
// 0:匹配的字符串
// index:匹配开始的索引
while((temp = exp.exec(str)) != null){
console.log(exp.lastIndex);//下一次匹配开始的位置
console.log(temp[0]);
}
</script>
</body>
</html>
<script>
// 日期转换案例
// 将字符串‘12342534200,sdfg,Date(12436143500)’转换成日期对象
var str = '12342534200,sdfg,Date(12436143500)';
var t = eval(str.replace(/.*(Date\(\d+\)).*/g,'new $1'));
console.log(t.toString());
</script>
var m = '12,34,56'
undefined
m.replace(/\d{2}/g,'"$&"')
""12","34","56""
**15.DOM**
① ```javascript // (执行代码段,间隔执行代码段的函数) var t = setInterval(function(){ console.log(new Date()); },1000); // (执行函数,延迟毫秒数) setTimeout(function(){ // console.log('en'); console.log(t); clearInterval(t); },5000)
```javascript
<script>
//标题 跑马灯效果
// console.log(document.title);
// 每隔0.5s让title最后一个文字到最前面去;
setInterval(function(){
// 使用字符数组
// 数组pop()可以从数组最后位置弹出一个元素,unshift()从数组头部添加元素
//把字符串转化成字符数组
var charArray = document.title.split('');
// 让字符数组的最后一个元素出数组
var lastChar = charArray.pop();
// 把最后的元素插入到最开头
charArray.unshift(lastChar);
// 转换成字符串返回
var newTitle = charArray.join('');
document.title = newTitle;//把标题改到浏览器上去
},500);
</script>
②querySelector(selectors);
<body>
<!-- querySelector(selectors) -->
<!-- 根据css选择器选取元素,返回element对象 -->
<!-- querySelectorAll(selectors) -->
<!-- 返回满足css选择器的所有元素 ,返回nodeList类型的对象-->
<div class="c1">diyigg</div>
<p class="tm">kk</p>
<p class="ll">jjj</p>
<p class="ll">lll</p>
<h3 class="tmd">mm</h3>
</body>
<script>
var element = document.querySelector(".c1");
console.dir(element);
var arr = document.querySelectorAll("p.ll");
console.log(arr);
// arr是一个nodeList实例
arr.forEach(function(elem,index){
console.log(index+":"+elem.innerHTML);
});
</script>
</html>
③事件响应方法
<body>
<div class="c1">diyigg</div>
<!-- 绑定一个事件 -->
<!-- 事件的三要素:事件源,事件名,执行方法 -->
<p>kk</p>
<p class="ll">jjj</p>
<p class="ll">lll</p>
<h3 class="tmd">mm</h3>
</body>
<script>
var d = document.querySelector('.c1');
d.onclick = function(){
// 在事件响应方法中,this指向当前事件源对象;
alert(this.innerHTML);
};
//这种绑定事件的方式只能绑定一次
</script>
<script>
// //给所有li标签绑定事件并弹出内容
var liNodeList = document.querySelectorAll('#cityList li');
// liNodeList.forEach(function(element, index){
// // 绑定点击事件
// element.onclick = function(){
// alert(this.innerHTML);
// };
// //
// });
liNodeList.forEach(function(element,index){
//直接将元素的事件响应方法指向一个声明函数
element.onclick = liOnClickHander;
});
//li触发事件响应方法
function liOnClickHander(){
alert(this.innerHTML);
}
</script>
④事件流
点击了子元素标签的时候,父元素的绑定的点击事件也会被执行。原因:事件冒泡;
事件分为捕获阶段和冒泡阶段。捕获信息就是事件信息从顶层向下层传递的过程,冒泡是事件反应处理从底层向上层反馈的过程。
</style>
</head>
<body>
<input id = "btn" type="button" value="点我">
<div class="parent">parent
<div class="child">child</div>
</div>
<script>
// (DOM2级绑定事件)
var btn = document.querySelector('#btn');
//这种绑定事件的方式不能绑定多个事件,只能在冒泡阶段执行事件响应程序
// btn.onclick = function(){
// }
//事件类型,事件处理程序,是否在捕获阶段执行事件处理;
btn.addEventListener('click',function(){
alert('按钮被点击');
},false);//(默认)是否在捕获阶段触发事件响应方法
// 可绑定多个,顺序执行
btn.addEventListener('click',function(){
alert('按钮又被点击了');
});
// 在捕获阶段
var p = document.querySelector('.parent');
var c = document.querySelector('.child');
p.addEventListener('click',function(){
alert('父亲');
},true);
p.addEventListener('click',function(){
alert('孩子');
},true);
</script>
⑤ 点击变图形事件
第一种方法:循环嵌套,存在内存消耗
<style>
.wjx{
width: 600px;
margin: 400px auto;
}
span{
font-size: 60px;
cursor: pointer;
}
</style>
</head>
<body>
<div class="wjx">
<span>☆</span>
<span>☆</span>
<span>☆</span>
<span>☆</span>
<span>☆</span>
</div>
<script>
var star = document.querySelectorAll('.wjx span');
star.forEach(function(element,index){
element.addEventListener('click',function(){
// 把自己设置成实心五角星,其他空心
star.forEach(function(wjx,index){
wjx.innerHTML = '☆';
});
element.innerHTML = '❤';
});
});
</script>
第二种方法:优化
var star = document.querySelectorAll('.wjx span');
// 循环问题,一定要注意内存消耗问题
star.forEach(function(element,index){
element.addEventListener('click',wjxClickHandler);
});
function wjxClickHandler(){
star.forEach(function(wjx,index){
wjx.innerHTML = '☆';
});
// element.innerHTML = '❤'; //访问不到
// 事件处理函数的作用域中this指向当前注册时间的标签元素
this.innerHTML = '❤';
}
⑥自动添加列
<body>
<input type="button" value="添加" id="btnAdd">
<ul class="list"></ul>
<script>
// 要求:li的内部文件从1开始,每点击一次,自动添加一个li
var btn = document.querySelector('#btnAdd');
var index = 1;
btn.addEventListener('click',function(){
var list = document.querySelector('.list');
list.innerHTML += "<li>" + index + "<li>";
index++;
});
</script>
</body>
⑦DOM0/2级绑定事件和解绑
<body>
<input type="button" id="btnClick" value="点击" >
<input type="button" id="btnRemove" value="解除">
</body>
<script>
var btnClick = document.querySelector('#btnClick');
var btnRemove = document.querySelector('#btnRemove');
// DOM0级绑定事件
btnClick.onclick = function(){
alert('DOM0 级点击事件');
};
// DOM2级绑定事件
btnRemove.addEventListener('click',function(){
btnClick.onclick = null;
// 给btnClick解绑dom2级别事件
btnClick.removeEventListener('click',btnClickHander);
});
// DOM2级事件绑定和解绑
btnClick.addEventListener('click',btnClickHander);
// 事件处理程序
function btnClickHander(){
alert('DOM2级绑定事件');
}
</script>
⑧浏览器兼容事件
if(el.addEventListener){
el.addEventListener('click',modify,false);
}else if(el.attachEvent){
el.attachEvent('onclick',modifyText);
}
//例:兼容IE浏览器和其他浏览器
if(btn.addEventListener){
btn.addEventListener('click',clickHandler);
}else{
btn.attachEvent('onclick',clickHandler);
}
funtion clickHandler(){
alert("兼容处理");
}
⑨获取时间对象及兼容处理
var btn = document.querySelector('#btnClick');
btn.onclick = function(e){
// 标准浏览器中,e就是事件对象;
// ie浏览器中是通过window.event属性获取当前的事件对象;
e = e ? e:window.event;//兼容ie和标准浏览器获取的事件对象
console.dir(e);
}
⑩阻止事件冒泡和默认行为
<style>
div{
width: 200px;
height: 200px;
border: 1px solid black;
}
</style>
</head>
<body><div class="parent" id = "pDiv">
<input type="button" value="点击" id = "btn">
</div>
<script>
var btn = document.getElementById('btn');
// 阻止事件冒泡
btn.onclick = function(e){
// 兼容ie和标准模式浏览器
e = e || window.event;
// 判断是否是点击自己
if(e.taeget === this || e.srcElement === this){
// 取消事件冒泡
if(e.sopPropagation){
e.stopPropagation();//标准浏览器使用(既可以阻止事件冒泡也可以阻止事件捕获)
}else{
e.cancleBubble = false;//ie6-8浏览器
}
}
};
var pDiv = document.getElementById('pDiv');
pDiv.onclick = function(e){
alert('div');
}
</script>
//阻止默认处理
<body>
<a href="http://baidu.com" id="linkTalaoma">laoma</a>
<script>
var linkTalaoma = document.getElementById('linkTalaoma');
linkTalaoma.onclick = function(e){
e = e || window.event;//兼容处理事件对象
// 标准浏览器
if(e.preventDefault){
e.preventDefault();
}else{
e.returnValue = false;
}
};
</script>
</body>
11.文本框只能输入数字
<body>
<input type="text" id="text">
<!-- //或者直接用H5新标签 type = number; -->
<script>
// onkeypress事件,当键盘上的键被按下时触发。
var text = document.getElementById('text');
text.onkeypress = function(e){
e = e || window.event;
// 事件对象中的keyCode属性就是你按下的键盘上的键的编码
if(e.keyCode < 48 || e.keyCode > 57){
return false;//当键盘按下了非数字键
};
}
</script>
</body>
12.浏览器在离开页面的时候提醒用户是否要离开DOM0级
<form action="http://baidu.com">
用户名:<input type="text">
<hr>
<input type="submit" value="提交">
</form>
<script>
window.onbeforeunload = function(){
return "离开啊"
}
</script>
var btnSub = document.getElementById('btnSub');
var txtName = document.getElementById('txtName');
btnSub.onclick = function(e){
if(!txtName.value){
alert('用户名不能为空');
return false;
}
};
13.事件类型
文档加载完成事件
window.onload();//页面中所有图片,内容加载完成后;
优化:
<script>
// 兼容一下:标准浏览器和ie浏览器浏览器 在文档加载完成后就立即绑定事件
//ie9 以上
document.addEventListener('DOMContentLoaded',function(e){
console.log("DOMContentLoaded"); // 先执行
var btn = document.getElementById('btn');
btn.addEventListener('click',function(){
alert("ok");
});
},false);
//所有的窗口中元素都加载完成后触发不包括ajax请求的内容
window.onload = function(){
console.log("window.onload");//后执行
};
//ie8 文档加载完成后绑定事件
document.onreadystatechange = function(e){
console.log(document.readyState);
if(document.readyState == "complete"){
var btn = document.getElementById("btn");
btn.onclick = function(){
alert('ok');
}
}
}
</script>
<body>
<input type="button" value="点击" id = "btn">
</body>
//以上方法过于繁琐麻烦,下面优化,封装在一个方法中
<script>
document.myReady = function(callback) {
// 封装标准浏览器好人ie浏览器
if(document.addEventListener){
document.addEventListener('DOMContentloaded',callback,false);
}else if(document.attachEvent){
// 兼容ie8及以下浏览器
document.attachEvent('onreadystatechange',function(){
// 当文档的状态变为:interactive表示,文档dom对象可以进行访问。
if(document.readyState == "interactive"){
callback(window.event);
}
});
}else{
window.onload = callback;
}
};
document.myReady(function(e){
// 注册事件
var btn = document.getElementById('btn');
btn.onclick = function(){
alert('okk');
};
});
</script>
14.滚动条
window.onscroll = function(e){
// 滚动条
console.log('scroll');
// 纵向滚动距离,标准浏览器 ie不支持
console.log(window.pageYOffset);
//ie下滚动测距||标准页面下
console.log(document.documentElement.scrollTop||document.body.scrollTop);
};