全部JavaScript内容整理,全文除前面内容因知识较琐碎或为了更好的表达而用了部分图片外,共计约6万字,全手打。全部整理在一起而不是分开来写,主要是方便以后有疑问直接Ctrl + F搜索文档,即可查询。
JS主要分为3部分,即 ECMAScript , DOM,BOM。移动端暂时没写进来。
因时间仓促,每天凌晨挤时间整理,难免有遗漏,以后发现后会回来补。
话不多说,干货奉上~
bit byte kb Gb Tb
如图:
css决定网页呈现给用户的模样(决定好不好看)。相当于给人穿衣服、化妆等。比如这样:
JS脚本语言---- 编程类语言
实现业务逻辑和页面控制(决定功能)。相当于人做出的各种动作。比如这样:
特点:
①可以将单行或者少量JS代码写在HTML标签的事件属性中(以on开头的属性),如:onclick。
②注意单双引号的使用:在THML中推荐使用双引号,在JS中推荐使用单引号。
③可读性差,在HTML中编写JS大量代码时,不方便阅读;
④引号易错,引号多层嵌套匹配时,非常容易弄混淆。
⑤在特殊情况下使用。
2,内嵌式。写在被head标签包含。比如:
<head>
<script>
alert('hello world');
</script>
</head>
特点:①可以将多行JS写到
<body>
<div>
</div>
...
<script src="js/my.js"></script>
</body>
①利于HTML页面代码结构化,把大段JS代码独立到HTML页面之外,既美观,又方便文件级别的复用。
②引用外部JS文件的
/* 内容
内容
内容*/
//声明一个名称为age的变量。
var age;
①var是JS的一个关键字。用来声明变量(variable变量的意思)。使用该关键字声明变量后,计算机会自动为变量分配内存空间,不需要程序员管。
②age是程序员定义的变量名。我们要通过变量名来访问内存中分配的空间。
2,给变量赋值。
age = 10;//给age这个变量赋值为10.
① = 用来把右边的值 赋给左边的变量空间中。此处代表赋值的意思。
②变量值是程序员保存到变量空间里的值。
3,变量的初始化。
var age = 18; //声明变量同时赋值为18.
声明一个变量并赋值,我们称之为变量的初始化。
var age = 18;
age = 19;//最后的结果就是19.因为18被新赋值的19给覆盖了。
2,同时声明多个变量
同时声明多个变量时,只需要写一个var,多个变量名之间使用英文逗号隔开。比如:
var age = 10, name = 'zs', sex = 2;
3,声明变量的特殊情况。
①只声明,不赋值。比如:
var age;
console.log(age);
输出结果就是 undefined。
②不声明,只赋值。
age = 10;
console.log(age);
输出结果是 10.
③不声明,不赋值
console.log(age);//没声明,也没赋值
输出结果时直接报错。
/*JS的变量数据类型是只有程序在运行过程中,
根据等号右边的值来确定的。*/
比如:
var age = 10; //这个age变量是一个数字型。
var areYouOk = '是的'; //这是一个字符串。
//在代码运行时,变量的数据类型是由JS根据等号右边的变量值的数据类ing来判断的。
//运行完毕后,变量就确定了数据类型。
JS拥有动态类型,同时也意味着相同的变量科用作不同的类型。比如:
var x = 6; //变量x是数字。
var x = 'Bill'; //现在x是字符串了。
数字型的三个特殊值
Infinity -Infinity NaN
判断一个变量是否为非数字型: isNaN() 。
var strMsg = 'haha';
alert(strMsg.length);//输出结果是4
拼接号 + 的口诀: 数值相加,字符相连。
还有一种常用情形: 字符串 + 变量 + 字符串
比如:
var age = 18;
console.log('我今年' + age + '岁了');//输出结果:我今年18岁了
console.log(ture + 1);//2
console.log(false + 1); //1
Number.isInteger(3) // true
Number.isInteger(3.1) // false
Number.isInteger('') // false
Number.isInteger('3') // false
Number.isInteger(true) // false
Number.isInteger([]) // false
算术运算符优先级问题: 先乘除,后加减,有()就先算()里面的。
注意:‘37’ == 37 true ==会把字符串型的37转化为数字型的37,然后再和37进行比较。
===就不会转换了。
console.log(1 && 2);//结果: 2
console.log(0 && 6);//结果: 0
||的短路运算。
和&&刚好相反。 如果表达式1的结果为真,则返回表达式1,就根本不会再去看表达式2写的什么了,表达式2根本就不会有执行的机会; 如果表达式1为假,那么返回表达式2.
console.log(1 || 2);//结果: 1
console.log(0 || 1);//结果: 1
if(条件语句) {
执行语句;
} else {
执行语句;
}
----
if() {
}
else if {
}
else if {
} ...
else {
}
-----
三元表达式: 条件表达式 ? 执行语句1 : 执行语句2
------
switch (表达式) {
case 值1: 执行语句1;
break;
case 值2: 执行语句1;
break;
...
default:
最后执行语句;
}
/*就是拿着switch表达式的值和case的值进行匹配,
匹配到哪个就输出哪个,匹配后退出。最后匹配不到,就执行最后语句。
匹配的时候,必须是===全等关系,即值和类型都一样,才可以匹配。
如果当前的case里面没有break,就会继续执行下一个case,不管当前有没有匹配上。
直到遇到break为止,才会退出。*/
for(初始化变量; 条件表达式; 操作表达式){
被循环的语句;
}
for(var i = 1; i <= 100; i++) {
console.log('hello world');
}
执行顺序:1,先执行var i = 1;
2,再执行判断语句 i <= 100;
3,接着执行 console.log('hello world');
4,最后执行 i++
5,第二轮:这时候 i的值变成2 了, 仍然是先执行var i = 1; 依此类推。
断点判断法,判断执行顺序。 F12 里面 sources 找到需要调试的文件 在程序的某一行设置断点。
------------------------
while(条件表达式){
循环体代码;
}
do {
循环体代码-条件表达式为true时 重复执行循环体代码;
}while(条件表达式);
意思是 退出当前条件下的循环,直接跳到下一次的循环继续进行。
例如,小朋友能吃5个包子,当他准备吃第3个包子的时候,发现包子里有虫子,然后把第3个包子扔掉了,继续去吃第4个包子和第5个包子。 所以他一共只吃了4个包子。
意思是 退出从当前条件下的剩余所有循环。到此就终止所有循环了。
例如,小朋友能吃5个包子,当他准备吃第3个包子的时候,发现包子里有虫子,一气之下把第3个包子扔掉了,接着第4个和第5个包子也扔掉了。所以他一共只吃了2个包子。
var 数组名 = new Array();
var arr = new Array();//创建了一个新的空数组
2,用数组字面量创建数组[ ](更简单)
//1,使用数组字面量方式创建空的数组
var arr = [];
//2,使用数组字面量方式创建带初始值的数组
var arr1 = ['1','haha','pink']
//定义数组
var arrStus = [1,2,3];
//获取数组中的第二个元素
console.log(arrStus[1]);
//操作数组的行为,都是通过操作索引号来完成的。
用循环可以遍历数组。
//就是直接让length属性等于另外一个值。
两两比较,交换位置。
函数的使用:先声明一个函数,再调用函数。
//声明函数
function 函数名() {
//函数体代码
}
//function是声明函数的关键字,必须小写。
/*由于函数一般是为了实现某个功能才定义的,
所以通常我们将函数名 命名为动词,比如getSum*/
//调用函数
函数名();//通过调用函数名来执行函数体代码。
//调用的时候千万不要忘记添加()
/*口诀: 函数不调用,自己不执行。
即 声明函数本身并不会执行代码,只有调用函数时才会执行函数体代码。*/
//声明时:
function 函数名(形参1,形参2...) {
...
}
//调用时:
函数名(实参1,实参2...)
形参就是不用声明的变量。
用法举例:
function cook(aru) {
console.log(aru);
}
cook('番茄炒蛋');
cook('黄瓜炒蛋');
function getSum(num1, num2) {
return num1 + num2;
}
console.log(getSum(1, 2));
return最多只能返回一个值。
如果确实需要返回多个值,可以用数组。return[值1, 值2…]。
函数如果有return,则返回return后面的值。
如果没有return,返回的是undefined 。
return的另一个用处: 终止return后面的代码。也就是函数中return后面的代码不会再被执行。
//arguments的使用
function fn() {
console.log(arguments);//里面存储了所有传递过来的实参。
console.log(arguments.length);
console.log(arguments[2]);
//我们可以按照数组的方式遍历arguments
for(var i = 0;i < arguments.length; i++) {
console.log(arguments[i]);
}
}
//调用上面的函数。
fn(1, 2, 3);
fn(1,2,3,4,5);
arguments应用举例:
//利用函数求任意个数的最大值
function getMax() {
var max = arguments[0];
for(var i = 0; i < arguments.length; i++) {
if(arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(1,2,3));
console.log(getMax(11,2,34,444,5,100));
因为每个函数都是独立的代码块,用于完成特殊任务,因此经常会用到函数相互调用的情况。
举例:function fn1() {
console.log(111); //这里是执行的第**二**步。 输出111.
**fn2();** //这里是执行的第**三**步。 调用fn2()函数。
console.log('fn1'); //第**六**步。fn1()函数还没执行完,继续执行。 输出fn1.
}
function fn2() {
console.log(222); //这里是执行的第**四**步。 开始执行fn2()函数里的语句。输出222.
console.log('fn2'); //这里是执行的第**五**步。 输出fn2.
}
fn1(); //执行顺序:上面的fn1()和fn2()函数都还没调用,不执行。这里是第**一**步。 调用fn1()函数。
两种声明方式:
1,利用函数关键字自定义函数(命名函数)function fn() {
...
}
fn();//调用函数。
//这种声明方式就是前面讲的构造函数的方式。
2,函数表达式(匿名函数)
var 变量名 = function() {
...
}
变量名();//调用函数
注意:
1,函数表达式声明方式跟声明变量差不多,
只不过变量里面存的是一个函数。
2,函数表达式也可以传递参数。比如:
var fun = function(aru) {
console.log('我是函数表达式');
}
fun('pink');
注意:如果在函数内部,没有声明,直接赋值的变量,也属于全局变量。例如:
正常的声明变量 var num1 = 10;这个在函数中声明,就是局部变量。
如果直接写 num2 = 20; 那么num2就是一个全局变量了。(但是这种情况要避免使用。以免混淆)
console.log(num);//undefined
var num = 10;
//相当于执行了以下代码,先预解析,再执行:
var num;
console.log(num);
num = 10;
fun();//报错
var fun = function() {
console.log(22);
}
//相当于执行了以下代码
var fun;
fun();
fun = function() {
console.log(22);
}
案例1:结果是几?
//案例1
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
------------------
预解析:
var num = 10;
function fun() {
var num;
console.log(num);
num = 20;
}
fun();
//最后输出是 defined;
//案例2:结果是几?
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a=b=c=9;
console.log(a);
console.log(b);
console.log(c);
}
--------预解析小知识点----------
var a=b=c=9;
//相当于 var a = 9;
b = 9;
c = 9;
b和c直接赋值,没有var声明。所以b和c是全局变量。
而a有var声明,所以是函数内的局部变量。
如果改成var a = 9, b = 9, c = 9;那么,a b c都被var声明了,就都是函数内的局部变量。这种声明方式叫集体声明。
var arr = ['张三疯', '男', 128, 154];
里面的值分别代表什么呢?数组可以存储值,但是不能完整的把意思表达清楚。
而JS中的对象表达结构更清晰,更强大。张三疯的个人信息在对象中的表达结构如下:
var obj = {};//这样就创建了一个空对象
//像不像数组的字面量创建方式:var arr = [];
var obj = {
uname: '张三疯',
age: 18,
sex: '男',
sayHi: function() {
console.log('hi~');
}
}
//对象创建好了,怎么使用呢?
//(1)调用对象的属性 对象名.属性名。如:
console.log(obj.uname);
//(2)调用方法2: 对象名['属性名']
console.log(obj['age']);
//(3)调用对象的函数sayHi 对象名.方法名()
//千万不要忘记小括号
obj.sayHi();
如上,uname这些属性后面需要加逗号,同理,sayHi函数如果后面还有函数,这个函数写完后,仍然需要加逗号,和下一个函数隔开。(是不是很像数组存储值的方式??)
2,利用new Object创建对象
var obj = new Object();//创建了一个空对象
obj.uname = '张三疯';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
console.log('hi~');
}
//外面是利用等号 = 赋值的方法,添加对象的属性和函数
//每个属性和方法之间用分号结束;
3,利用构造函数创建对象
为什么需要使用构造函数?
前面的两种创建对象方式 依次只能创建一个对象。每次创建一个对象后,对象之间有很多的属性和方法是相同的。只能一直复制。 所以可以利用函数的方法,重复这些相同的代码,这样的函数就叫 构造函数。
构造函数和普通函数不一样的是,它里面封装的是对象,而非普通的可重复代码。
构造函数 就是把对象里面一些相同的属性和方法抽象出来 封装到函数里。
//利用构造函数创建对象
//我们想要创建四大天王的对象 相同的属性有:名字 年龄 性别
//相同的方法有: 唱歌
//构造函数的语法格式:
function 构造函数名() {
this.属性 = 值;
this.方法 = function() {}
}
new 构造函数名();
-----------开始创建对象--------
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(songs);
}
}
var ldh = new Star('刘德华', 18, 男);//调用函数返回的是一个对象
//console.log(typeof ldh);
console.log(ldh.name);
console.log(ldh['sex'];
ldh.sing('冰雨');
-------------------
var zxy = new Star('张学友', 19, '男');
console.log(zxy.name);
console.log(zxy.age);
zxy.sing('吻别');
注意:
1,构造函数名字首字母要大写。
2,我们构造函数不需要return,就可以返回结果。
3,我们调用构造函数,必须用new
4,我们只要new Star() 调用函数就创建一个对象。如ldh {}
5,我们的属性和方法前面必须添加this 。
为啥要用this. 因为对象一定是具体的事物,name不是具体事物,加个this. 就是特指这个名字,就是具体的对象了。
//遍历对象的格式
for(变量 in 对象) {
}
------------应用举例------------
for(var k in obj) {
console.log(k);//k变量输出,得到的是属性名
console.log(obj[k]);//obj[k]得到的是 属性值
}
function getRandom(min, max) {
return Math.floor(Math.random()*(max-min + 1))+ min);
}
console.log(getRandom(1, 10));
//Date()日期对象。 是一个构造函数。
//必须使用new 来调用创建我们的日期对象
var arr = new Array();//创建要给数组对象
var obj = new Object();//创建一个对象实例
//1,使用Date 如果没有参数,返回所用电脑设备的当前时间
var date = new Date();
console.log(date);
/*2,参数常用的写法:
数字型 2019,10,01
字符串型 '2019-10-1 8:8:8'*/
var date1 = new Date(2019,10,1);
console.log(date1);//返回的是11月,不是10月,有点特殊
var date2 = new Date('2019-10-1 8:8:8');
console.log(date2);
需要获取日期指定的部分,所以我们要手动得到这种格式。
方法名 | 说明 | 代码 |
---|---|---|
getFullYear() | 获取当年 | dObj.getFullYear() |
getMonth() | 获取党羽(0-11) | dObj.getMonth() |
getDate() | 获取当天 | dObj. getDate() |
getDay() | 获取星期几(周日0到周六6) | dObj.getDay() |
getHours() | 获取当前小时 | dObj.getHours() |
getMinutes() | 获取当前分钟 | dObj. getMinutes() |
getSeconds() | 获取当前秒数 | dObj.getSeconds() |
//格式化日期 年月日
var date = new Date();
console.log(date.getFullYear());//输出当前的年份 2020
console.log(date.getMonth() + 1);//输出当前月份
//getMonth给的年份比实际年份小1个月 记得月份+1哦
console.log(date.getDate());//输出当前是几号
console.log(date.getDay());//当前是周五,输出值是5
//周日对应0 周一对应1 ...周六对应6
------------------------
//案例:写一个输出值为2020年4月24日 星期五
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
var day = date.getDay();
console.log('今天是' + year + '年' + month + '月' + dates + '日' + arr[day]);
//格式化 时分秒
var date = new Date();
console.log(date.getHours());//时
console.log(date.getMinutes());//分
console.log(date.getSeconds());//秒
//案例:封装一个函数 输出当前的时分秒 格式08:08:08
function getTimer() {
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
console.log(getTimer());
//获得Date总的毫秒数 不是当前时间的毫秒数
//而是距离1970年1月1号过了多少毫秒
//1,通过valueOf() getTime()
var date = new Date();
console.log(date.valueOf());
//就是我们当前时间 距离1970.1.1 总的毫秒数
console.log(getTime());
//2,简单的写法(最常用的写法)
var date1 = +new Date();
//+new Date() 返回的就是总的毫秒数
console.log(date1);
//3,H5新增的 获得总的毫秒数
console.log(Date.now());
//创建数组的两种方式
//1,数组字面量创建
var arr = [];//创建了一个空数组
var arr1 = [1,2,3];//创建时可以直接赋值。
console.log(arr[0]);
//1,new Array() 和创建对象很像
var arr2 = new Array();//创建了一个空数组
var arr3 = new Array(2);//创建了一个数组长度为2的数组
//也就是说,里面有2个数组元素
var arr3 = new Array(2,3);
//等价于[2,3] 这样写表示 里面有2个数组元素,是2和3
console.log(arr3);
方法2: Array.isArray(arr)
方法名 | 说明 | 返回值 |
---|---|---|
push(参数1…) | 末尾添加一个或多个元素,会修改原数组 | 并返回新的长度 |
pop() | 删除数组最后一个元素,把数组长度减1,无参数、会修改原数组 | 返回它删除的元素的值 |
unshift(参数1…) | 向数组的开头添加一个或更多元素,会修改原数组 | 并返回新的长度 |
shift() | 删除数组的第一个元素,数组长度减1 ,无参数、会修改原数组 | 并返回第一个元素的值 |
//添加 删除数组元素的方法
//1,push() 在数组的末尾 添加一个或者多个数组元素
var arr = [1,2,3];
console.log(arr.push(4,'pink'));//5
console.log(arr);//[1, 2, 3, 4, "pink"];
------------------
//2,unshift()在数组开头添加一个或者多个数组元素
console.log(arr.unshift('red', 'purple'));//7
console.log(arr);//["red", "purple", 1, 2, 3, 4, "pink"]
------------------
//3,pop()它可以删除数组的最后一个元素
console.log(arr.pop());//pink
console.log(arr);//["red", "purple", 1, 2, 3, 4]
-------------------
//4,shift()它可以删除数组的第一个元素
console.log(arr.shift());//red
console.log(arr);//["purple", 1, 2, 3, 4]
方法名 | 说明 | 是否修改原数组 |
---|---|---|
reverse() | 反转数组中元素的顺序,无参数 | 会改变原来的数组,返回新数组 |
sort() | 对数组的元素进行排序 | 会改变原来的数组,返回新数组 |
//1,翻转数组
var arr = [1,2,3,4];
console.log(arr.reverse());//[4, 3, 2, 1]
console.log(arr);//[4, 3, 2, 1]
//2,数组排序(冒泡排序)
var arr1 = [13,4,77,1,7];
arr1.sort(function(a,b) {
//return a - b;让数组按照升序的顺序排序
return b - a;//让数组按照降序的顺序排序
});
console.log(arr1);//[77, 13, 7, 4, 1]
//用 indexOf(数组元素)
//意思是返回该数组元素的索引号 从前往后查找
//它只返回第一个满足条件的索引号
//它如果在该数组里面找不到该数组元素,则返回 -1
var arr = [1,3,4,1,9];
console.log(arr.indexOf(1));//0
//封装一个去重的函数unique 独一无二的
//var arr = ['c','a','z','a','x','a','x','c','b'];
function unique(arr) {
var arr1 = [];
for(var i = 0; i < arr.length; i++) {
if(arr1.indexOf(arr[i]) === -1) {
arr1.push(arr[i]);
}
}
return arr1;
}
var demo = unique(['c','a','z','a','x','a','x','c','b']);
console.log(demo);//["c", "a", "z", "x", "b"]
方法名 | 说明 | 返回值 |
---|---|---|
toString() | 把数组转换成字符串,每项中间用逗号隔开 | 返回一个字符串 |
join(‘分隔符’) | 把数组转换成字符串,并且改变每个字符间的分隔符号 | 返回一个字符串 |
//1,toString() 将我们的数组转换为字符串
var arr = [1,2,3];
console.log(arr.toString());//1,2,3
//2,join('分隔符')
console.log(arr.join());//1,2,3
console.log(arr.join('-'));//1-2-3
console.log(arr.join('&'));//1&2&3
方法名 | 说明 | 返回值 |
---|---|---|
concat() | 连接两个或多个数组arr1.concat(arr2),不影响原数组 | 返回连接后的新数组 |
slice() | 数组截取slice(begin的索引号, end的索引号) ,这里的索引号包含左不包含右 | 返回被截取元素组成的新数组,不会影响原数组 |
splice() | 指定删除数组的某些元素splice(第几个索引号开始,要删除几个)。同时还可以向新数组里添加新的元素,splice(第几个索引号开始,要删除几个,要添加的元素) | 返回被删除项目的新数组,会影响原数组 |
//1,concat()
var arr = [1,2,3,4,5];
var arr1 = [6,7];
console.log(arr.concat(arr1));//[1, 2, 3, 4, 5, 6, 7]
console.log(arr.slice(0,2));//[1, 2]
console.log(arr.splice(2,2));//[3, 4]
console.log(arr);//[1, 2, 5]
var arr1 = [5,6,7,8,9];
arr1.splice(2,0,10);
document.write(arr1);//5,6,10,7,8,9
console.log(arr1);//[5, 6, 10, 7, 8, 9]
var str = 'abc';
str = 'hello';
//当重新给str赋值的时候,常量'abc‘不会被改变,依然在内存中
//重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
//由于字符串的不可变,在大量拼接字符串的时候会有效率问题
var str = '';
for(var i = 0; i < 10000; i++;) {
str += i;
}
console.log(str);
//这个结果需要花费大量时间来显示,因为需要不断的开辟新的空间
//字符串对象 根据字符返回位置 str.indexOf('要查找的字符', [起始的索引号位置])
var str = '改革春风吹满地,春天来了';
console.log(str.indexOf('春');//不写起始位置,默认从头开始查找
console.log(str.indexOf('春', 3));
//从索引号是3的位置开始往后查找
var str = 'oabcoefoxyozzopp';
var index = str.indexOf('o');//第一个'o'出现的位置
var num = 0;
while(index !== -1) {
//console.log(index);
document.write(index);
num++;
index = str.indexOf('o', index + 1);
}
//console.log('o出现的次数是:' + num);
document.write('o出现的次数是:' + num);
方法名 | 说明 | 使用说明和举例 |
---|---|---|
charAt(index) | 返回指定位置的字符(index是字符串的索引号) | str.charAt(0)就是返回str字符串索引号为0的字符 |
charCodeAt(index) | 返回指定位置的字符的ASCII码(index是索引号) | str.charCodeAt(0) |
str[index] | 获取指定位置的字符 | HTML5,IE8+支持,和charAt()等效 |
核心算法:
1,利用charAt()遍历整个字符串
2,把字符串里面的每个字符,都存储给对象。如果该对象没有属性(即这个字符在对象里存储的次数为0),那么次数就赋值为1,如果这个字符在对象里已经存储了,就让存储次数自增1
3,遍历这个对象,得到最大值和该字符
var str = 'avcoefoxyozzopp';
var o = {};//创建一个空对象o
//遍历字符串
for(var i = 0; i < str.length; i++) {
//chars 是字符串里的每一个字符
var chars = str.charAt(i);
if(o[chars]) {//如果o对象里还没有存储这个chars属性(即字符)
o[chars]++;//那么这个chars字符存储的字数就自增1
} else {
//这个字符已经在o对象里还没有存储,那就让存储的次数等于1
o[chars] = 1;
}
}
console.log(o);//Object {a:1 c:1 e:1 f:1 o:4 p:2 v:1 x:1 y:1 z:2}
//现在每个字符都在o对象里存储了,开始遍历o对象
var max = 0;
var ch = '';
for(var k in o) {
//k是属性名(即存储的字符)
//0[k]就是属性值,即该字符在o对象里存储的次数
if (o[k] > max) {
max = o[k];//把存储的次数赋值给max
ch = k;//把存储的字符赋值给ch
}
}
console.log(max);//输出次数 4
console.log(ch);//输出该次数最多的字符 o
//
方法名 | 说明 |
---|---|
str1.concat(str2) | concat()方法用于连接两个或多个字符串。拼接字符串,等效于 + ,但是 + 拼接法更常用 |
substr(start, length) | 从start(索引号)位置开始,length取的个数,重点记住这个 |
slice(start, end) | 从start位置开始,截图到end位置,不包含end 。这里的开始和结束都是索引号 |
substring(start, end) | 从start位置开始,截取到end位置,不包含end 。基本和slice相同,但是开始和结束位置不能是负数 |
//字符串操作方法
//1,concat(str1,str2,str3…)
var str1 = 'i';
var str2 = ' love';
console.log(str1.concat(str2));// i love
//2,substr(start, length)
var str = "hello";
console.log(str.substr(2,2));// ll
值类型:简单数据类型 / 基本数据类型, 在存储时变量中存储的是值本身,因此叫做值类型。
如,string , number , boolean , undefined , null
但是null比较特殊。 null类型返回的是一个空对象。
var timer = null;
console.log(typeof timer);// object
/*如果有个变量我们以后打算存储为对象,
但是暂时又没想号放啥,这个时候就可以给null*/
引用类型:复杂数据类型,在存储时变量中存储的仅仅是地址(引用),因此叫做引用数据类型。
通过new关键字创建的对象,如Object,Array,Date等,都是引用类型。
通俗的讲,就是形参就是一个可以改变的参数,不管怎么改,在传来实参的时候,都不影响函数的调用。
function fn(a) {
a++;
console.log(a);
}
var x = 10;
fn(x);
console.log(x);
function Person(name) {
this.name = name;
}
function f1(x) {
console.log('1,' + x.name);//实参p把name 刘德华 传给了形参
x.name = "张学友";//给形参赋值
console.log('2,' + x.name);//对形参输出
}
var p = new Person("刘德华");
console.log('3,' + p.name);//刘德华
f1(p);
console.log('4,' + p.name);//实参操作了形参对应的对象,输出等同于x.name
/*
3,刘德华
1,刘德华
2,张学友
4,张学友
*/
学到这里。js的第一部分 即 ECMAScript就学完了。
-------------------------------------------------
JS 基础学习 ECMAScript 基础语法为后面做铺垫,Web APIs 是 JS 的应用,大量使用 JS基础语法做交互效果。
<body>
<div id="time">2019-9-9</div>
<script>
//1,因为我们文档页面是从上往下加载,所以先得有标签,所以我们的script写到标签的下面。
//2,get获得element 元素 by 通过 驼峰命名法
//3,参数 id 是大小写敏感的字符串
//4,返回的是一个元素对象
var timer = document.getElementById('time');
console.log(timer);
console.log(typeof timer);
//5,console.dir 打印我们返回的元素对象,更好的查看里面的属性和方法
console.dir(timer);
</script>
</body>
<body>
<ul>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<li>2333</li>
</ul>
<ul id="nav">
<li>666</li>
<li>666</li>
<li>666</li>
<li>666</li>
</ul>
<script>
//1,返回的是 获取过来的元素对象集合 以伪数组的形式存储的
var lis = document.getElementsByTagName('li');
console.log(lis);
console.log(lis[0]);
//2,我们想要依次打印里面的元素,我们可以采取遍历的方式
for(var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
//3,element.getElementsByTagName() 可以得到这个元素里面的某些标签
var nav = document.getElement('nav');
var navLis = nav.getElementByTagName('li');
console.log(navLis);
</script>
</body>
第2个和第3个获取元素方式,选择器必须带符号。类的选择器就加’ . ',ID选择器就加个#
<body>
<button id="btn">唐伯虎</button>
<script>
//点击一个按钮,弹出对话框
//1,事件是由三部分组成 事件源 事件类型 事件处理程序 我们也称为事件三要素
//(1)事件源 就是 谁发生 --按钮
//谁发生就把谁获取过来,先获取再操作
var btn = document.getElementById('btn');
//(2)事件类型 怎么发生 比如鼠标点击
//(3)事件处理程序 发生什么
//通过一个函数赋值的方式完成,发生的内容都在函数里
btn.onclick = funtion() {
alert('点秋香');
}
//谁发生 btn
//怎么发生 onclick
//发生什么 alert
</script>
</body>
鼠标事件 | 触发条件 |
---|---|
onclick | 鼠标点击左键触发 |
ondbclick | 鼠标双击触发 |
onmouseover | 鼠标经过触发 |
onmouseout | 鼠标离开触发 |
onfocus | 获得鼠标焦点触发 |
onblur | 失去鼠标焦点触发 |
onmousemove | 鼠标移动触发 |
onmouseup | 鼠标弹起触发 |
onmousedown | 鼠标按下触发 |
oncontextmenu | 禁用右键菜单 |
onselectstart | 禁止选中文字 |
二者都是鼠标移出。mouseout冒泡。 mouseleave不冒泡。(出去冒泡,离开不冒泡)
mouseout对应上面的mouseover ,mouseleave对应上面的mouseenter。
谁发生.addEventListener(怎么发生,发生了什么的函数)
//例如上面的唐伯虎点秋香例子
btn.addEventListener('click', function() {
alert('点秋香');
})
element.innerText
//从起始位置到终止位置的内容。但它去除html标签,同时空格和换行也会去掉
element.innerHTML
//起始位置到终止位置的全部内容,包括html标签,同时保留空格和换行
<p>2333</p>
<script>
var p = document.getElementByTagName('p');
console.log(p.innerText);
console.log(p.innerHTML);
</script>
type , value , checked , selected , disabled
<body>
<button>按钮</button>
<input type="text" value="输入内容" />
<script>
//1,获取元素
var btn = document.querySelector('button');
var inp = document.querySelector('input');
//2,注册事件--谁发生 怎么发生 发生什么
btn.addEventListener('click', function() {
//inp.innerHTML = '被点击了'; 这个是 普通盒子 比如div标签里面的内容被修改,不是value里的内容被改变
//表单里面的值 文字内容是通过valve来修改的
inp.value = '我被点击了';
//如果想要某个表单被禁用,不能重复点击disabled 我们想要这个按钮 button禁用
//btn.disbled = true; 这样就被禁用了
this.disabled = true;//这里的this就是btn,因为是btn发生的,这里的this就特指btn了。
//this指向的是发生的那个元素 btn
})
</script>
</body>
案例:京东登陆界面的密码表单
输入密码时,默认不显示密码。点击小眼睛图标时,显示密码。再点击又不显示密码。
//2,注册事件 谁发生 怎么发生 发生什么
var flag = 0;
eye.addEventListener('click', function() {
//每次点击 flag一定要变化
if(flag == 0) {
pwd.type = 'text';
eye.src = '---';
flag = 1;//这里就是要变化了。原来是0,这里就要变成1
} else {
pwd.type = 'password';
eye.src = '---';
flag = 0;//这里又变化了。原来是1,点过一次就变成0了
}
})
注意:
第3条里,如果原来的类名还想保留,那就可以这样做,假如原来的类名是class=‘first’ ,现在要用的是class='change’并且不想把原来的first类型替换掉,那就写成 元素.className = ‘first change’ 就阔以了。
<body>
<div></div>
<script>
//1,获取元素
var div = document.querySelector('div');
//2,注册事件。谁发生 怎么发生 发生什么
div.onclick = function() {
//div.style里面的属性 采取驼峰命名法
this.style.backgroundColor = 'purple';
this.style.width = '200px';
}
</script>
</body>
这里是this是指向函数的调用者,即div在调用这个函数。 相当于div.style (如上图的div)
如果调用者不是当前的元素,就不能用this了。(如下图function里的box.style 就不能写成this.style)
因为是btn在调用函数,然后让box产生变化。 如果用了this,就是指btn在发生变化了。所以这里不能用this。
当一个元素需要更改的样式较多时,适合用element.className来完成。<head>
<style>
.change {
background-color: purple;
color: #fff;
font-size: 25px;
margin-top: 100px;
}
</style>
</head>
<body>
<div>文本</div>
<script>
//当元素样式较多或者功能复杂的情况下,
//使用element.className获得修改元素样式,
var div = document.querySelector('div');
div.onclick = function() {
this.className = 'change';
}
</script>
</body>
如果有同一组元素,我们想要其中一个元素实现某种样式的情况下,不想让其他同样的元素跟着实现这种样式,就需要用到循环的排他思想算法:
<ul class='baidu'>
<li><img src='1' /></li>
<li><img src='1' /></li>
<li><img src='1' /></li>
</ul>
<script>
//1,获取元素
var imgs = document.querySelector('.baidu').querySelectorAll('img');
//console.log(imgs);
//2,循环注册事件
for(var i = 0; i < imgs.length; i++) {
imgs[i].onclick = function() {
//this.src 就是我们点击的图片的路径
//console.log(this.src);
//把这个路径this.src给body就可以了
document.body.style.backgroundImage = 'url(' + this.src + ')';
}
}
</script>
说白了,就是先让包括自己的所有人都不显示,然后再让自己显示。 这样在自己显示的时候,别人就不显示了。
<script>
//1,全选和取消全选的做法:
//让下面所有复选框的checked属性(选中状态) 跟随 全选按钮即可
//获取元素
var j_acAll = document.getElementById('j_cbAll');
var j_tbs = document.getElementById('j_tb').getElementByTagName('input');
//即 选出下面所有的复选框
//注册时间 谁发生 怎么发生 发生什么
j_cbAll.onclick = function() {
//this.checked 它可以得到当前复选框的选中状态
//如果是true 就是选中, 如果是false 就是未选中
console.log(this.checked);
for(var i = 0; i < j_tbs.length; i++) {
j_tbs[i].checked = this.checked;
}
}
//2,下面的复选框需要全部选中,上面全选才能选中做法:
//给下面所有复选框绑定点击事件,每次点击,都要循环看是否都选中了
for(var i = 0; i < j_tbs.length; i++) {
j_tbs[i].onclick = function() {
//flag控制全选按钮是否选中
var flag = true;
//每次点击下面的复选框都要循环检查这4个小按钮是否全被选中
for(var i = 0; i < j_tbs.length; i++) {
if( !j_tbs[i].checked) {
flag = false;
break;
//退出for循环 这样可以提高运行效率
//因为只要一个没有选中,剩下的就无需再循环判断了
}
}
j_cbAll.checked = flag;
}
}
</script>
//每次点击,都要循环
作用:获取内置属性值,即元素本身自带的属性
作用:可以获得原有属性值,也可以获得自定义的元素值。主要获取自定义的属性 (标准) 我们程序员自定义的属性。
获取、设置、移除元素属性的应用例子:
<body>
<div id="demo" index="1"></div>
<script>
var div = document.querySelector('div');
//1,获取元素的属性值
//(1)element.属性
console.log(div.id);//demo
//(2)element.getAttribute('属性')
//程序员自己添加的属性,我们称为自定义属性,比如这里的 index
console.log(div.getAttribute('id'));//demo
console.log(div.getAttribute('index'));//1
//2,设置元素的属性值
//(1)element.属性 = ‘值’;
div.id = 'test';
div.className = 'navs';
//(2)element.setAttribute('属性','值');
//主要针对自定义属性
div.setAttribute('index', 2);
div.setAttribute('class', 'footer');
//class特殊 这里写的就是class 不是className
//3,移除属性 element.removeAttribute('属性');
div.removeAttribute('index');
</script>
</body>
<script>
//获取元素
var tab_list = document.querySelector('.tab_list');
var lis = tab_list.querySelectorAll('li');
var items = document.querySelectorAll('.item');
//for循环绑定点击事件
for(var i = 0; i < lis.length; i++) {
//开始给5个小li设置索引号index
lis[i].setAttribute('index',i);
lis[i].onclick = function() {
//1,上面的模块选项卡,点击某一个,当前这个底色会是红色,其他选项卡不变色。
//所以用到排他思想。干掉所有人,其余的li清除class这个类
for(var i = 0; i < lis.length; i++) {
lis[i].className = '';
}
//留下我自己
this.className = 'current';
//2,下面的显示内容模块
var index = this.getAttribute('index');
console.log(index);
//干掉所有人 让其余的item 这些div 隐藏
for(var i = 0; i < items.length; i++) {
items[i].style.display = 'none';
}
//留下我自己 让对应的item显示出来
items[index].style.display = 'block';
}
}
</script>
H5规定自定义属性data- 开头做为属性名并且赋值。说白了就是,自定义属性要用data- 做开头。比如:
<div data-index="1"></div>
或者使用JS设置:
element.setAttribute('data-index', 2)
1,element.getAttribute(‘data-index’) 兼容性好
2,H5新增 element.dataset.index 或者element.dataset[‘index’] , ie11才开始支持,而且只能取data- 开头的自定义元素属性。
如果自定义属性里有多个 - 连接的单词,我们获取的时候,采取驼峰命名法。如 div.dataset.listName 或 div.dataset[‘listName’]
网页中的所有内容都是节点(标签,属性,文本,注释,空格等),在DOM中,节点使用node来表示。
HTML DOM树中的所有节点均可通过JS进行访问,所有HTML元素(节点)均可被修改,也可以创建或删除。一般地,节点至少拥有nodeType(节点类型),nodeName(节点名称)和nodeValue(节点值)这三个基本属性。
node.parentNode
<div class="demo">
<div class="box">
<span class="erweima">X</span>
</div>
</div>
<script>
//1,父节点parentNode
var erweima = document.querySelector('.erweima');
//var box = document.querySelector('.box');
//得到的是离元素最近的父级节点(亲爸爸)
//如果找不到父节点,就返回null
console.log(erweima.parentNode);
</script>
第一种: parentNode.childNodes(标准)
//虽然是标准的,但是不提倡使用
parentNode.childNodes 返回包含指定节点的子节点的集合。该集合为即时更新的集合。
注意:返回值里面包含了所有的子节点,包括元素节点,文本节点(文字,空格,换行等)等。 如果只想要获得里面的元素节点,则需要专门处理。所以我们**一般不提倡使用childNodes** 。 专门处理需要的代码:var ul = document.querySelector('ul');
for(var i = 0; i < ul.childNodes.length; i++) {
if(ul.childNodes[i].nodeType == 1) {
//即 ul.childNodes[i]是元素节点
console.log(ul.childNodes[i];
}
}
第二种: parentNode.children(非标准)
//虽然是非标准,但是可以得到我们想要的元素节点,
//所以推荐使用这个
parentNode.children是一个只读属性,返回所有子元素节点,其余节点不返回。所以重点掌握这个方法。
1.获取第一个子元素节点, parentNode.children[0];
2,获取最后一个子元素节点,
parentNode.children[parentNode.children.length - 1]
这样既可以获得想要的元素节点,又不存在兼容性问题。
<script>
//1,获取元素
var nav = document.querySelector('.nav');
var lis = nav.children;//得到4个小li
//2,注册循环事件 点谁谁发生
for(var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function() {
this.children[i].style.display = 'block';
}
lis[i].onmouseout = function() {
this.children[i].style.display = 'none';
}
}
</script>
返回当前元素的下一个兄弟节点,找不到则返回null 。同样,也是包含所有的节点。
返回当前元素上一个兄弟节点,找不到则返回null。同样,也包含所有的节点。
返回当前元素下一个兄弟元素节点,找不到则返回null。
返回当前元素的上一个兄弟元素节点,找不到则返回null。
3和4取出来的确实是想要的兄弟节点,但是会有兼容性问题。
如何解决兼容性问题?
需要自己封装一个函数。
function getNextElementSibling(element) {
var el = element;
while(el == el.nextSibling) {
if(el.nodeType === 1) {
return el;
}
}
return null;
}
不过兄弟节点用的较少。
document.createElement('tagName');
创建 由tagName指定的HTML元素。因为这些元素原先不存在,是根据我们的需求 动态生成的,所以我们也称为动态创建元素节点。
将一个节点添加到指定父节点的子节点列表末尾。类似于css里面的after伪元素。node是父节点,child是子级。
将一个节点添加到父节点的指定子节点前面。类似于css里面的before伪元素。
<body>
<ul>
<li>2333</li>
</ul>
<script>
//1,创建元素节点
var li = document.createElement('li');
//2,添加后节点 node.appendChild(child)
var ul = document.querySelector('ul');
ul.appendChild(li);
//添加前节点 node.insertBefore(child,指定元素);
var lili = document.creatrElement('li');
ul.insertBefore(lili,ul.children[0]);
</script>
</body>
<body>
<textarea name="" id=""></textarea>
<button>发布</button>
<ul>
</ul>
<script>
//1,获取元素
var btn = document.querySelector('button');
var text = document.querySelector('textarea');
var ul = document.querySelector('ul');
//2,注册事件 谁发生 怎么发生 发生什么
btn.onclick = function() {
if(text.value == "") {
alert('内容不能为空!');
return false;
} else {
//(1)创建元素节点
var li = document.createElement('li');
//先创建li 才能赋值
li.innerHTML = text.value;
//(2)添加节点
ul.insertBefore(li,ul.children[0]);
}
}
</script>
</body>
node.removeChild(child)
//举例:
ul.removeChild(ul.children[0]);
从DOM中删除一个子节点,返回删除的节点。
node.cloneNode()
//返回调用该方法的节点的一个副本。
//这里的node是要被克隆的那个元素节点
注意:
<body>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
var ul = document.querySelector('ul');
var liCopy = ul.children[0].cloneNode();
ul.appendChild(liCopy);
</script>
</body>
<!DOCTYPE html>
<html>
<head>
<meta charset="uft-8" />
</head>
<body>
<button>点击</button>
<div class="inner"></div>
<ul class="create"></ul>
<script>
//1,document.write()创建元素
var btn = document.querySelector('button');
btn.onclick = function() {
document.write('2333');
}
//2,innerHTML 创建元素
var inner = document.querySelector('.inner');
var arr = [];
for(var i = 0; i <= 10; i++) {
arr.push('233');
}
inner.innerHTML = arr.join(' ');
//3,document.createElement()创建元素
var create = document.querySelector('.create');
for (var i = 0; i <= 10; i++) {
var li = document.createElement('li');
create.appendChild(li);
}
</script>
</body>
</html>
eventTarget.onclick = function(event) { };
或
eventTarget.addEventListener('click', function(event) { })
//这个event就是事件对象。可以写成e或者evt。
//这个参数在前面学习中是没有写出来的。
官方解释:event对象代表事件的状态,比如键盘按键的状态,鼠标的位置,鼠标按钮的状态。
解决:
e = e || window.event;
事件对象属性方法 | 说明 |
---|---|
e.target | 返回触发事件的对象 标准 |
e.srcElement | 返回触发事件的对象 非标准 ie6-8使用 |
e.type | 返回事件的类型 比如 click,mouseover 不带on |
e.cancelBubble | 该属性阻止冒泡 非标准 ie6-8使用 |
e.returnValue | 该属性组织默认事件(默认行为) 非标准 ie6-8使用 比如不让链接跳转 |
e.preventDefault() | 该方法组织默认事件(默认行为) 标准 比如不让链接跳转 |
e.stopPropagation() | 阻止冒泡 标准 |
if(e && e.stopPropagation) {
e.stopPropagation();
} else {
window.event.cancelBubble = true;
}
用法:
<body>
<div class="father">
<div class="son">son儿子</div>
</div>
<script>
//常见事件对象的属性和方法
//阻止冒泡 dom 推荐的标准 stopPropagation()
var son = document.querySelector('.son');
son.addEventListener('click', function(e) {
alert('son');
e.stopPropagation();//停止传播
e.canselBubble = true;//非标准 取消泡泡
},false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
alert('father');
},false);
document.addEventListener('click', function() {
alert('document');
}
</script>
</body>
<body>
<ul>
<li>2333</li>
<li>2333</li>
<li>2333</li>
<li>2333</li>
</ul>
<script>
//事件委托的核心原理:给父节点添加监听器,
//利用事件冒泡影响每一个子节点。
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
//alert('2333');
//e.target 可以得到我们点击的对象
e.target.style.backgroundColor = 'pink';
})
</script>
</body>
鼠标事件对象 | 说明 |
---|---|
e.clientX | 返回鼠标相对于浏览器窗口可视区的X坐标 |
e.clientY | 返回鼠标相对于浏览器窗口可视区的Y坐标 |
e.pageX | 返回鼠标相对于文档页面的X坐标 IE9+支持(常用) |
e.pageY | 返回鼠标相对于文档页面的Y坐标 IE9+支持 (常用) |
e.screenX | 返回鼠标相对于电脑屏幕的X坐标 |
e.screenY | 返回鼠标相对于电脑屏幕的Y坐标 |
<style>
img {
position: absolute;
top: 2px;
}
</style>
<body>
<img src=''>
<script>
var pic = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
console.log(x, y);//输出x 和 y坐标
//千万不要忘记给left和top添加px单位!
pic.style.left = x + 'px';
pic.style.top = y + 'px';
});
</script>
</body>
键盘事件 | 触发条件 |
---|---|
onkeyup | 键盘上的某个按键被松开时触发 |
onkeydown | 键盘上的某个按键被按下时触发 |
onkeypress | 键盘上的某个按键被按下时触发,但是它不识别功能键 比如 ctrl shift 4个方向键等 |
注意:
1,如果使用addEventListener,就不需要加on
2,三个事件的执行顺序是: keydown-keypress-keyup
键盘事件对象 属性 | 说明 |
---|---|
keyCode | 返回该键的ASCII值 |
注意:onkeydown和onkeyup不区分字母大小写,onkeypress区分字母大小写。
在我们实际开发中,我们更多的使用keydown和keyup,它能识别所有的键(包括功能键)
Keypress不识别功能键,但是keyCode属性能区分大小写,返回不同的ASCII值。
<body>
<input type="text">
<script>
//核心思路:检测用户是否按下了s键。
//如果按下了s键,就把光标定位到搜索框里面。
//使用键盘事件对象里面的keyCode,
//判断用户按下的是否是s键。
//搜索框获得焦点:使用js里面的focus()方法
var sch = document.querySelector('input');
document.addEventListener('keyup', function(e) {
if(e.keyCode == 83) {
sch.focus();
}
})
</script>
</body>
--------------------DOM---end------------------------
BOM(Brower Object Model)即浏览器对象模型。它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window 。
BOM由一系列相关的对象构成,并且每个对象都提供了很多方法和属性。
BOM缺乏标准,JS语法的标准化阻止是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape(就是网景公司)浏览器标准的一部分。
BOM构成
BOM比DOM更大,它包含DOM。
window对象是浏览器的顶级对象。它具有双重角色。
1,它是JS访问浏览器窗口的一个接口。
2,它是一个全局对象。定于在全局作用域中的变量和函数都会变成window对象的属性和方法。
在调用的时候可以省略window,前面学习的对话框都属于window对象方法,比如alert() ,prompt()等。
注意:window下的一个特殊属性 window.name
window.onload = function() { }
或者
window.addEventListener('load', function() { })(推荐使用,因为没有次数限制)
window.onload是窗口(页面)加载事件,当文档内容完全加载完成时会触发该事件(包括图像,脚本文件,css文件等),就会调用处理函数。
注意:
1,有了window.onload就阔以把JS代码写在页面元素的上方,因为onload是等页面内容全部加载完毕,再去执行处理函数的。
2,window.onload传统注册事件方式只能写一次,如果有多个,会以最后一个window.onload为准。
3,如果使用window.addEventListener则没有限制。
另一种情况:(加载较慢的情况)
document.addEventListener('DOMContenLoaded', function() { })
DOMContentLoaded事件触发时,仅当DOM加载完成时,不包括样式表,图片,flash等等。
IE9以上才支持。
如果页面的图片很多的话,从用户访问到onload触发可能需要较长的事件,交互效果就不能实现,必然影响用户的体验,此时用DOMContentLoaded事件比较合适。
window.onresize = function() {}
window.addEventListener('resize', function() {})
window.onresize是调整窗口大小加载事件,当触发时就调用的处理函数。
注意:
1,只要窗口大小发生像素变化,就会触发这个事件。
2,我们经常利用这个事件完成响应式布局。window.innerWidth是当前屏幕的宽度。
window.setTimeout(调用函数,延迟的毫秒数);
setTimeout()方法用于设置一个定时器,该定时器在定时器到期后执行调用函数。
注意:
1,window可以省略。
2,这个调用函数可以直接写函数,或者写函数名, 或者 '函数名()'三种形式。但是不推荐最后一种写法。
3,延迟的毫秒数可以省略,默认是0,如果写,必须是毫秒数。不需要带单位。
4,因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
//语法规范: window.setTimeout(调用函数,延迟时间);
//setTimeout(function() {
// console.log('午时已到');
//}, 2000);
function callback() {
console.log('立即斩首');
}
setTimeout(callback, 3000);
回调函数 callback
window.setTimeout(调用函数,延迟的毫秒数);
setTimeout()这个调用函数,我们也称为回调函数callback。
普通函数是按照代码顺序直接调用。
而这个函数,需要等待时间,时间到了才能取调用这个函数,因此我们称为回调函数。
简单理解:回调,就是回头调用的意思。上一件事干完,再回头调用这个函数。
以前讲的element.onclick = function() {}或者element.addEventListener(‘click’, fn);里面的函数也是回调函数。
window.clearTimeout(timeout ID)
注意:
1,window可以省略。
2,里面的参数就是定时器的标识符。
window.setInterval(回调函数,间隔的毫秒数);
setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数。
这是与setTimeout()最大的不同。setTimeout()定时器只调用一次回调函数。
注意:
1,window可以省略。
2,这个调用函数可以直接写函数,或者函数名或者采用字符串 ’ 函数名() ’ 三种形式。
3,间隔的毫秒数可以省略,默认是0,如果写,必须是毫秒数,不用带单位。
4,因为定时器可能有很多,所以我们经常给定时器赋值一个标识符。
案例:自动倒计时
<body>
<div>
<span class="hour">1</span>
<span class="minute">2</span>
<span class="second">3</span>
</div>
<script>
//1,获取元素
var hour = document.querySelector('.hour');
var minute = document.querySelector('.minute');
var second = document.querySelector('.second');
var inputTime = +new Date('2019-5-1 18:00:00');//用户输入时间总的毫秒数
countDown();//现调用一次函数,防止第一次刷新页面出现空白
//2,开启定时器
setInterval(countDown, 1000);
function countDown() {
var nowTime = +new Date();
//返回的是当前时间总的毫秒数
var times = (inputTime - nowTime) / 1000;
//times是剩余需要倒计时的总的秒数
var h = parseInt(times / 60 / 60 / % 24);//小时
h = h < 10 ? '0' + h: h;
//格式搞的好看一点
hour.innerHTML = h ;
//把倒计时的小时数给小时盒子
var m = parseInt(times / 60 % 60);//分钟
m = m < 10 ? '0' + m: m;
minute.innerHTML = m;
var s = parseInt(times % 60);//秒
s = s < 10 ? '0' + s: s;
second.innerHTML = s;
}
</script>
</body>
同步
前一个任务结束后再执行后一个任务,程序的执行顺序与任务排列顺序是一直的,同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了(10分钟后),再去切菜,炒菜。异步
在做一件事情时,因为这件事情会话费很长时间。在做这件事情的同时,还可以去处理其他事情。比如做饭的异步做法,在烧开水的同时,利用这10分钟,去切菜,炒菜。同步任务
同步任务都在主线程上执行,形成一个执行线。异步任务
JS的异步是通过回调函数实现的。 一般而言,异步任务有以下三种类型: 1,普通事件,如click,resize等 2,资源加载,如load,error等 3,定时器,包括setTimeout,setInterval等。 异步任务相关回调函数添加到任务队列中,任务队列也称为消息队列。执行机制:任务分成同步任务和异步任务。先执行完同步任务,再去执行异步任务。
1,先执行 执行栈中的同步任务。2,异步任务(回调函数)放入任务队列中。
3,一旦执行栈中的所有同步任务执行完毕,系统就会按照次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)。
protocol://host[:port]/path/[?query]#fragment
如:
http://www.itcast.cn/index.html?name=andy&age=18#link
组成 | 说明 |
---|---|
protocol | 通信协议 常用的http, ftp, maito等 |
host | 主机(即域名) 比如 www.itheima.com |
port | 端口号 可选, 省略时使用方案的默认端口 如http的默认端口为80 |
path | 路径 由 零或多个’/'符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 |
query | 参数 以键值对的形式,通过&符号分隔开来 |
fragment | 片段 #后面内容 常见于链接 锚点 |
location对象的属性 | 返回值 |
---|---|
location.href | 获取或者设置 整个URL |
location.host | 返回主机(即域名) |
location.port | 返回端口号 如果未写 空字符串 |
location.pathname | 返回路径 |
location.search | 返回参数 |
location.hash | 返回片段 #后面的内容 常见于链接 锚点 |
案例:获取URL参数数据:数据在不同网页中传递
第一个页面:输入信息的界面
<body>
<form action="index.html">
用户名:<input type="text" name="uname">
<input type="submit" value="登录" />
</form>
</body>
第二个页面:接收信息的界面
<body>
<div></div>
<script>
console.log(location.search);//?uname=andy
//1,先去掉? substr('起始位置', 截取几个字符);
var params = location.search.substr(1);//uname=andy
//2,利用 = 号把字符串分割为数组 split('=');
var arr = params.split('=');
console.log(arr);//["uname", "ANDY"]
var div = document.querySelector('div');
//3,把数据写入div中
div.innerHTML = arr[1] + "欢迎您";
</script>
</body>
location对象的方法 | 返回值 |
---|---|
location.assign() | 跟href一样,可以跳转页面,也称为重定向页面 |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相遇刷新按钮或者F5 如果参数为true 强制刷新 相当于ctrl + f5 |
下面前端代码可以判断用户哪个中断打开的页面,实现跳转:
if((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobild|BlackBerry|IEMobild|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)) {
window.location.href = ""; //手机
} else {
window.location.href = ""; //电脑
}
//把这个代码赋值到里面就阔以了。
//要查哪个网页地址,就把地址补齐到href里。
window对象给我们提供了一个history对象,与浏览器历史纪录进行交互。该对象包含用户(在浏览器窗口中)访问过的URL。
history对象的方法 | 作用 |
---|---|
back() | 可以实现后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能 参数如果是1 前进1个页面 如果是-1 后退1个页面 |
history.back();
history.forward();
history.go(1);
offset系列常用属性:
offset系列属性 | 作用 |
---|---|
element.offsetParent | 返回作为该元素带有定位的父级元素,如果父级都没有定位 则返回body |
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回值不带单位 |
只有上和左,没有下和右。
client系列属性 | 作用 |
---|---|
element.clientTop | 返回元素上边看的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不含边框,返回值不带单位 |
element.clientHeight | 返回自身包括padding、内容区的高度,不含边框,返回值不带单位 |
注意和offset的区别。clientWidth是不含边框的。
<body>
<script>
//1,立即执行函数:不需要调用,立马能够子级执行的函数
function fn() {
console.log(1);
}
fn();
//2,写法也可以传递参数进来
//(function() {})()或者(function() {}())
(function(a, b) {
console.log(a + b);
var num = 10;
})(1, 2);//第二个小括号可以看作是调用函数
(function sun(a, b) {
console.log(a + b);
var num = 10;//局部变量
}(2, 3));
//3,立即执行函数最大的作用就是 独立创建了一个作用域,
//里面所有的变量都是局部变量,不会右命名冲突的情况。
</script>
</body>
scroll系列属性 | 作用 |
---|---|
element.scrollTop | 返回被卷去的上侧距离,返回值不带单位 |
element.scrollLeft | 返回被卷去的左侧距离,返回值不带单位 |
element.scrollWidth | 返回自身实际的宽度,不含边框,返回值不带单位 |
element.scrollHeight | 返回自身实际的高度,不含边框,返回值不带单位 |
常用的是 element.scrollTop和element.scrollLeft。
window.pageXOffset 和 window.pageYOffset属性,返回文档在窗口左上角水平和垂直方向滚动的像素。
pageXOffset设置或返回当前网页相对于窗口显示区左上角的X位置。pageYOffset设置或返回当前页面相对于窗口显示区左上角的Y位置。
pageXOffset 和pageYOffset属性相当于scrollX和scrollY属性。
这些属性是只读的。
function getScroll() {
return {
left: window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0,
top: window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0,
}
}
//使用的时候
getScroll().left
<script>
//简单动画函数封装obj目标对象 target 目标位置
function animate(obj, target) {
var timer = setInterval(function() {
if (obj.offsetLeft >= target) {
//运动到一定距离,就停止计时器
clearInterval(timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 200);
}
var div = document.querySelector('div');
//调用函数
animate(div, 300);
</script>
<script>
//var obj = {};
//obj.name = 'andy';
//简单动画函数封装obj是目标对象 target 是目标位置
//给不同的元素指定了不同的定时器
function animate(obj, target) {
obj.timer = setInterval(function() {
if(obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 200);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
//调用函数
animate(div,300);
animate(span, 200);
</script>
改进版:
<script>
//当我们不断的点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
//解决方案就是 让我们元素只有一个定时器执行
//先清除以前的定时器,只保留当前一个定时器执行
clearInterval(obj.timer);
function animate(obj, target) {
obj.timer = setInterval(function() {
if(obj.offsetLeft >= target) {
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 200);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
//调用函数
animate(div,300);
animate(span, 200);
</script>
//开始设置一个变量
var flag = true;
if(flag) {
flag = false;
do something...//关闭水龙头
}
//利用回调函数,动画执行完毕后,
flag = true;//打开水龙头
x是距离文档左边的距离,y是距离文档顶部的距离。x和y都不带单位。