js:跨平台的脚本语言(脚本语言:不能独立运行,要依赖于网页)
javascript组成:
1、ECMAScript 3,4 5,6,7
2、DOM 文档
3、BOM 浏览器打开一个窗口,这一个窗口就代表一个BOM
【注】所有的js代码在一个script标签中编写
属性:
1、type = ‘text/javascript’ 声明当前标签内写的文本格式(省略)
2、src = ‘demo.js’ 引入外部的.js文件
注意点:
1、可以有多个script标签,多个script标签是自上而下顺序执行
2、一个script标签只能专心的做一个事情
alert() 在当前页面上弹出一个警告框,警告框中显示要显示的内容
(1)alert()
(2)document.write() 在当前页面上输出内容
【注】如果内容中含有标签会自动解析。
转义字符: & and符号
< >
(3)console.log() 在控制台中输入内容,一般情况下用于代码调试。
小彩蛋:招聘简介。百度f12 console
【注】在编写JS代码的时候,要在每一行代码结束的位置加 ;(分号)。
代码压缩:电脑运行的时候,去掉编写代码的时候,有的所有空格、tab键和换行,形成一行。
alert('58');
document.write("helo");
console.log("hello world");
常量:值不可以改变的叫做常量。
数据类型:
基本数据类型:
数字
类型: number
例子:100 -20 3.14
布尔值
类型: boolean
例子: true false
字符串
类型:所有带单引号或者双引号的都叫做字符串。(单引号/双引号效果一样,必须成对)
例子: ‘hello’ “world” ‘100’ “3.14”
复合/引用数据类型(专门时间讲解)
特殊数据类型:
null 空
undefined
NaN (not a number)
变量:值可以被修改的叫做变量。
1、声明变量(必须声明以后才能使用)
关键字(系统征用的有特殊功能的单词叫做关键字): var 声明变量。
2、初始化:声明变量的时候,直接给这个变量赋值叫做初始化。
3、如果我们声明变量的时候,没有值赋给这个变量,系统默认赋值成undefined。
var num = null;
num = 10;
alert(num);//num值为空,10直接赋值
//【注】提高整个程序运行的效率,我们可以将声明变量,没有值赋值给这个变量的时候,默认赋值成null,提高程序运行效率。
var num;
num = 10;
alert(num);//程序会自动复制给num1,之后10替换
程序被CPU执行。
【注】程序磁盘读取到内存中,被CPU运行。
了解计算机的组成:
磁盘 内存 CPU/GPU
关键信息:内存有空间,程序本质上运行是在内存中运动的。
【注】编程就是合理的分配内存。
标识符:所有用户自定义的名字叫做标识符。
变量名也是标识符。
命名规则:
1、只能由数字、字母、下划线和美元符号($)组成
2、不能以数字开头
3、不能保留字和关键字
4、大写小敏感 age Age 这是两个完全不同的变量
5、见名思意(尽量使用英文全称)
6、单词个数超过两个的
<1>驼峰式命名
className
<2>下划线命名(烤串式命名))
class_name
变量:弱引用类型。赋值成什么数据类型就是什么数据类型。js是弱引用语言
【注】不建议改变变量的数据类型,容易引起歧义。
关键字:
typeof
格式: typeof 常量/变量
功能:输出当前常量或者变量的数据类型。
十进制
0~9
二进制 1 0
八进制
模八取余
十六进制
模十六取余
十进制转二进制
模二取余,固定流程
十进制数 52 转二进制 是 110100
110100
1 * 2^2 + 1**2^4 + 1*2^5 = 4 + 16 + 32 = 52;
可以先将十进制数转成二进制,再将二进制数转成对应八进制或者十六进制。
二进制转八进制:
规则:从右往左数,每三位一组,不足三位的用0补齐,最后将每一组数单独转成十进制数。
110 100
52的八进制数:64 => 4**8^0 + 6*8^1 = 52;
二进制转十六进制:
规则:从右往左数,每四位一组,不足四位的用0补齐,最后将每一组数单独转成十进制数。
0011 0100
52的十六进制数:34 => 3**16^1 + 4*16^0 = 52;
1、算术运算符
加 减 乘 除 %(取余符号)
【注】将不同数据类型进行算数运算。
自动数据类型转换:不同数据类型之间是没有办法进行运算,将数据转成同一数据类型,再进行计算。
1、其中有一个操作数必须是字符串,运算符必须是+号,别的数据类型转成字符串,进行字符串拼接。
2、任何数据和字符串做+加法以外的操作,那么字符串要先转成数字再去进行运算。
<1>如果字符串是一个纯数字字符组成的字符串,转成对应的数字
<2>如果字符串中含有除数字以外的别的字符,转成NaN,NaN和任何数据运算都是NaN。(not a number)
3、除字符串以外的数据,在进行算数运算的时候,先转成数字,再进行运算。
alert(10 + true); //true => 1
alert(10 + false); //false => 0
alert(10 - null); //null => 0
alert(10 + undefined); //undefined => NaN
计算机是不会进行小数运算。(天生有Bug)
小彩蛋:金融账户,只存储整数,单位是分。
在JS中除数可以为0
alert(10 / 0); //Infinity 无穷大
alert(-10 / 0); //-Infinity 无穷小
alert(Infinity + 'hello');//转成字符串
alert(Infinity + 100);//无穷大
alert(Infinity + -Infinity); //NaN
2、关系运算符(是用来表示判断的)
< >= <= == != === !==
关系运算符:
< >= <= == != =(恒等) !(恒不等)
【注】值,绝对是布尔值。
自动数据类型转换:
一、和其他运算符一样,当关系运算符操作非数值时要遵循一下规则:
<1>两个操作数都是数值,则数值比较;
<2>两个操作数都是字符串,则比较两个字符串对应的字符编码值;
ASIIC码表: 是电脑内部,每一个字符和字符对应编码的一张表。
(1)如果是两个单个字符进行比较,直接比较字符的ASIIC码值。
(2)逐位,进行比较,如果比较出大小,就直接得出结果。
<3>两个操作数有一个是数值,则将另一个转换为数值,再进行数值比较;
二、在相等和不等的比较上,如果操作数是非数值,则遵循一下规则:
<1>一个操作数是布尔值,则比较之前将其转换为数值,false 转成 0,true 转成 1;
<2>一个操作数是字符串,则比较之前将其转成为数值再比较
<3>一个操作数是 NaN,则==返回 false,!=返回 true;并且 NaN 和自身不等;
<4>===恒等,必须数字和数据类型都相等,返回true,否则返回false.
alert(Number("10") === 10);//首先强制转换为数字,就恒等了
alert(Number(null)); //0
alert(Number(undefined)); //NaN
alert(null == undefined); //true
3、逻辑运算符
&& || !
与运算
格式:
表达式1 && 表达式2
规律:只有当两个表达式都为true的时候,整个表达式才为真。
短路操作:当表达式1为false的时候,表达式2就不执行了,就直接得出结果为false。(后面会用)
或运算:
格式:
表达式1 || 表达式2
规律:只有当两个表达式都为false的时候,整个表达式才为假。
短路操作:当表达式1为true的时候,表达式2就不执行了,直接得出结果为true。(后面会用)
非运算:
格式:
!表达式
规律:现将表达式的值自动数据类型转换成布尔值,然后,再取反。
【注】非0即真,非空即真。
规律:
1.操作数是一个空字符串,返回 true;
2.操作数是一个非空字符串,返回 false;
3.操作数是数值 0,返回 true;
4.操作数是任意非 0 数值(包括 Infinity),false;
5.操作数是 NaN,返回 true;
6.操作数是 undefined,返回 true;
4、一元运算符
++ –
一元运算符:++ –
a++;
值:++后置,先取a的值作为a++表达式的值,然后再对a进行+1。
功能:对原有的变量进行+1操作。
++a;
值:++前置,先对a进行+1操作,再a的值作为++a表达式的值。
功能:对原有的变量进行+1操作。
a–
值:–后置,先取a的值作为a–表达式的值,然后再对a进行-1.
功能:对原有的变量进行-1操作。
--a
值:–前置,先对a进行-1操作,再a的值作为–a表达式的值。
功能:对原有的变量进行-1操作。
5、赋值运算符
<1>基本赋值运算符 =
<2>复合赋值运算符 += -= … x=
普通赋值运算符: = 功能:将=号右边的值,赋值给=号左边的变量。
复合赋值运算符: x= += -=
表达式:任何数据和运算符组成的式子叫做表达式。
<1>表达式的值
<2>表达式的功能
Boolean() 将其他的数据类型强制转换成布尔值
口诀: 非0即真,非空即真。
Number() 将其他的数据类型强制转换成数字
【注】只有纯数字字符组成的字符串转数字,才能转为数字,其他都为NaN.
parseInt()
1、取整
2、将别的进制转成十进制 必须传入字符串
52 十进制
二进制数 110100
八进制 64
十六进制 34
var str1 = "110100";
alert(parseInt(str1, 2));
var str2 = "64";
alert(parseInt(str2, 8));
var str3 = "34";
alert(parseInt(str3, 16));
parseFloat() 取浮点数
顺序结构:代码自上而下顺序执行。
分支结构/选择结构/条件构造:要根据不同的条件,执行不同的操作
(1)单分支语句:
语法:
if(判断的条件){
执行语句;(判断条件为true的时候执行)
}
(2)双分支语句:
语法:
if(判断的条件){
执行语句;(判断条件为true的时候执行)
}else{
执行语句;(判断条件为false的时候执行)
}
步骤:
1、确定判断条件应该写什么
2、根据不同的结果,编写对应的执行语句。
【注】if()里面可以写任何的表达式,都会自动数据类型转换成布尔值。所有非零的数转化为数字都是true。
循环结构:重复去做一件事情。
【注】什么时候用判断语句,我们就编写if语句。
(3)多分支语句:
if 多分支语句,需要判断的题目,只能用if语句
if else:
语法:
if(判断条件1){
执行语句1;
}else if(判断条件2){
执行语句2;
}
…
else{
执行语句;(上述所有条件都不成立,执行这里。)
switch多分支语句:表达式,直接计算表达式的结果,如果是匹配确定的结果,优先使用switch
语法:
switch(表达式){
case 常量1:
执行语句1;
break;
case 常量2:
执行语句2;
break;
…
default:
当上述所有的case选项都匹配失败,执行这里。
break;
}
过程:
1、计算switch()语句表达式的值
2、和case后续的的值进行匹配,匹配成功,执行对应case选项下的执行语句。
【注意:】
1、一般情况下不要省略break;,break代表的是终止当前的switch语句
2、一般情况下不要省略default;
选择结构-注意点
1. if后面的()不能省略,()后面不要加分号
2. if分支中即使一句话也要把{}写上
3. if嵌套不要超过三层
4. Switch语句里把default分支一定要写上,防 止在以后的维护中产生歧义
5. 把执行概率更大(正常情况)放在前面(if, case)
6. if else 一般来表示两个分支或者嵌套比较 少的分支,如果分支多的话,优先使用switch。
格式:
表达式1 ? 表达式2 : 表达式3;
执行:
1、先去判断表达式1是否为真
2、表达式1为真,直接去执行表达式2
3、表达式1为假,直接去执行表达式3
【注】本质是一个双分支语句。
|:一假即假
&:一真即真
^:当只有一个数位存放的是 1 时,它才返回 1。
左移运算:由两个小于号表示(<<)。它把数字中的所有数位向左移动指定的数量。例如,把数字 2(等于二进制中的 10)左移 5 位,结果为 64(等于二进制中的 1000000);
有符号右移运算符由两个大于号表示(>>):它把 32 位数字中的所有数位整体右移,同时保留该数的符号(正号或负号)。有符号右移运算符恰好与左移运算相反。例如,把 64 右移 5 位,将变为 2;
无符号右移运算符由三个大于号(>>>)表示,它将无符号 32 位数的所有数位整体右移。对于正数,无符号右移运算的结果与有符号右移运算一样。用有符号右移运算中的例子,把 64 右移 5 位,将变为 2;
重复去做一件事情。
三种语法:
while循环
do_while循环
for循环
(1)while循环:
格式:
while(循环条件){
循环语句;
}
//求1~100的和
var i = 1;
var sum = 0;
while(i <= 100){
sum += i;
i++;
}
alert(sum);
执行:如果循环条件成立就执行循环语句,知道循环条件不成立为止。
使用循环的好处:
1、代码简洁
2、代码没有冗余
3、后期维护方便
写循环的步骤:
1、确定循环的次数
【注】循环条件,while()可以写任意的表达式,最后都会自动数据类型转换成布尔值。
【注】不能让循环条件永远成立,会造成死循环。
2、确定每一次循环要执行的代码
(2)do…while循环(了解)
语法:
do{
循环语句;
}while(循环条件);
var i = 1;
var sum = 0;
do{
sum += i;
i++;
}while(i <= 100);
alert(sum);
【注】do…while循环后面的分号不要省略。
(3)for循环(最多))
格式:
for(表达式1; 表达式2; 表达式3){
执行语句;
}
死循环:循环条件永远成立。
while(1){
常用的。
}
do{
}while(1);
for(;;){
}
break: 功能:终止当前循环。
continue:功能:跳过这次循环,直接进入下次循环
概念:函数就是把完成特定功能的一段代码[抽象出来],使之成为程序中的一个[独立实体],起个名字(函数名)。可以在同一个程序或其他程序中多次重复使用(通过函数名调用)。
作用:
使程序变得简短而清晰;
有利于程序维护;
可以提高程序开发效率;
提高了代码的重用性(复用性)。
第一步,函数声明:(无参数无返回值)
function 函数名(){
函数体(具体要执行的代码);
}
【注】见名思意,函数名必须体现其功能。
第二步,函数调用:
格式:函数名();
(1)无参数无返回值
function 函数名(){
函数体(具体要执行的代码);
}
function print(){
for(var i=0;i<5;i++){
document.write("hello"+"");
}
}
print();
document.write("");
print();
(2)有参数无返回值的函数(【注】不确定的值。)
形参:形式上的参数。【注】使用起来和普通的变量没有区别。
格式:
function 函数名(形参1, 形参2…){
函数体;
}
调用函数:
格式:函数名(实参1, 实参2…);
实参:实际传入的参数。
传参:用实参给形参赋值。
function print(n){//n形式参数
for(i=0;i");
}
}
print(2);//2实参
(3)有参数有返回值
封装函数步骤:
1、分析不确定值
2、将不确定值声明称形参
3、函数名和形参名都要见名思意。
程序员可能对函数运行的结果有不同的处理方式。
【注】我们不能够将函数运行的结果写在函数里面。
return 关键字
有参数有返回值的函数:
格式:
function 函数名(形参1, 形参2…){
函数体;
return 表达式;
}
【注】return后面写什么的表达式,函数调用的结果就是return后面表达式的值。
【注】函数运行的时候,如果遇到return关键字,整个函数会终止。
function add(num1, num2){
//复杂的代码
return num1 + num2;
}
var res = add(10, 20);
alert(res);
var res2 = add(5, 6);
document.write(res2);
注】每一个函数内部都有有一个arguments,系统内置的。
【注】arguments是用来存储实际传入的参数。
属性:
arguments.length 输出当前里面存储的参数个数
访问某一个数据:
arguments[下标];
【注】下标是从0开始的。
【注】优先使用形参,除非特殊情况。
/*
例子:求传入任意个数字的和?
*/
function sum(){
// alert(arguments.length);
var res = 0; //求和的数
for(var i = 0; i < arguments.length; i++){
res += arguments[i];
}
return res;
}
var num = sum(10, 20, 30, 40, 50);
alert(num);
任何程序在执行的时候都要占用内存空间内。函数调用的时候也要去占用内存空间。
垃圾回收机制:调用函数的时候,系统会分配对应的空间给这个函数使用(空间大小一般情况由这个函数里声明的变量和形参决定)。
当函数使用完毕以后,这个内存空间要释放,还给系统。
【注】在函数内部声明的变量和形参是属于当前函数的内存空间里的。
内存管理机制:在函数中声明的变量和形参,会随着函数的调用被创建,随着函数的调用结束而被销毁。
在函数中声明的变量和形参,有效范围是当前函数(当前函数的大括号),作用域,局部作用域。
就近原则:离哪个作用域近,就使用哪个作用域内的同名变量。
局部作用域:一个函数的大括号。在这个函数内部声明的变量或者形参,只能在当前函数内部使用。
function show(){
var a = 2; //局部变量 局部作用域
a++;
alert(a);
}
show(); //3
show(); //3
alert(a); // a is not defined
全局作用域:整个页面。
var a = 2; //声明在全局作用域的变量叫做全局变量
function show(){
a++;
alert(a);
}
show();
show();
alert(a);
递归:
满足以下三个特点就是递归:
1、函数自己调用自己
2、一般情况有参数
3、一般情况下有return
【注】递归可以解决循环能做的所有的事情,有一些循环不容易解决的事情,递归也能轻松解决。
【注】递归,都可以写出来,但是不知道为什么是对的。
想要计算1-100相加的值(sum(100)),首先知道sum99的值,但是不知道,sum98的值,以此类推,sum99的值到sum2的值占用内存,计算机一直分配内存空间。
/*
递归:
方法:
1. 首先去找临界值,即无需计算,获得的值。
2. 找这一次和上一次的关系
3. 假设当前函数已经可以使用,调用自身计算上一次
sum(100) = sum(99) + 100;
sum(n) = sum(n - 1) + n;
*/
// 例一:计算1~n的和?
function sum(n){
if(n == 1){
return 1;
}
return sum(n - 1) + n;
}
alert(sum(100));
//例二:
/*
有一堆桃子不知数目,猴子第一天吃掉一半,觉得不过瘾,又多吃了一只,第二天照此办法,吃掉剩下桃子的一半另加一只,
天天如此,到第num(num <= 10)天早上,猴子发现只剩一只桃子了,问这堆桃子原来有多少只? (思路:n为还剩n天吃完的桃子数)
peach(10) / 2 - 1 = peach(9);
peach(10) = (peach(9) + 1) * 2;
peach(n) = (peach(n - 1) + 1) * 2;
*/
/*
还剩n天吃完的桃子数
*/
function peach(n){
if(n == 1){
return 1;
}
return (peach(n - 1) + 1) * 2;
}
// alert(peach(4));
/*
22
10
4
1
*/
数组:用一个变量存储一堆数据的数据结构。
声明数组:
1、通过new创建数组
参数:传入任意的数据,存储到数组中。
2、省略new运算符创建数组
【注】上述两种方法,传入参数只有一个,并且是数字的时候,直接声明这么长的一个数组。
3、数组常量进行赋值。(JS一般使用中括号[]);
//声明长度为10的数组,数组中没有数据。
// var arr = new Array(10);
var arr = Array(10);
数组的属性:
数组.length 返回值数组【元素】的个数。
元素:将数组存储的每一个数据,叫做数组的元素。
访问数组的元素: 数组[下标]; 下标是从0开始的。
【注】数组和循环是天生一对。
/*
for循环
for...in 遍历 快速遍历/快速枚举
*/
var arr = [10, 20, 30, 40, 50];
//在页面上分别将每一个数输出。
for(var i = 0; i < arr.length; i++){
document.write(arr[i] + "
");
}
/*
for(var i in arr){
document.write(arr[i] + "
");
}
*/
栈结构:
栈:木盆
结构:从同一头进,从同一头出。
特点:先进后出。
数组的两个方法形成栈结构:
push
格式:数组.push(参数1, 参数2…);
功能:给数组的末尾添加元素。
返回值:插完元素以后数组的长度。
pop
格式:数组.pop()
参数:没有参数
返回值:取下一个元素
功能:从数组末尾取下一个元素
alert(box.push("盐城”)); //数组末尾添加一个元素,并且返回长度
box.pop() //移除数组末尾元素,并返回移除的元素
队列结构
结构:从末尾进,从头部出。
特点:先进先出
shift()
格式:数组.shift()
参数:没有参数
功能:从数组的头部取下一个元素
返回值:取下的元素
unshift()
格式:数组.unshift(参数1, 参数2…)
功能:从数组的头部插入元素
返回值:插完元素以后数组的长度。
alert(box.push("深圳”)); //数组末尾添加一个元素,并且返回长度
alert(box.shift()); //移除数组开头元素,并返回移除元素
alert(box.unshift()); //数组开头添加两个元素
concat() 方法
格式:数组.concat(数组,数据,…);
功能:拷贝原数组,创建一个新数组。
返回值:合并成的新数组,原数组不会改变
var arr1 = [10, 20, 30, 40];
var arr2 = arr1.concat();
arr2.push(50, 60);
alert(arr1); //10,20,30,40
alert(arr2); //10,20,30,40,50,60
slice() 方法
格式:数组.slice=(start,end);[start,end)左闭右开
功能:可以基于当前数组获取指定区域元素 [start, end)
返回值:生成新的数组,原数组不会发生改变
var arr1 = [10, 20, 30, 40];
var arr2 = arr1.slice(1,3);
alert(arr2);//20,30
alert(arr1);//10,20,30,40
splice() 方法
格式:数组.splice(start,length,数据1,数据2)
参数:
start:开始截取的长度
length:截取的元素的长度
第三个元素开始:在start位置,插入的元素
var box = [10, 20, 30, 40];
splice中的删除功能: var box2 = box.splice(0, 2);//30,40
splice中的插入功能: var box2 = box.splice(1, 0, “钢铁侠”);//10,钢铁侠,20,30,40
splice中的替换功能: var box2 = box.splice(1, 2, 100);//10,100,40
join()
格式:数组.join(字符串)
功能:将数组中的元素,用传入的拼接符,拼接成一个字符串
返回值:拼接好的字符串。
var arr1 = [10, 20, 30, 40];
var arr2=arr1.join("==");
alert(arr1);
alert(arr2);//10==20==30==40
reverse() 逆序
var arr = [true, "hello", 100];
arr.reverse();
alert(arr);//100,hello,true
sort() 排序
格式:数组.sort() 默认从小到大排序,按照字符串排序。
参数:一个函数,代表要怎么去进行排序(固定用法)
按照字符串排序
var arr1 = [10,5,90,20,30,40];
arr1.sort();
alert(arr1);//10,20,30,40,5,90(按照字符串排序,5是最大的)
数值大小排序
var arr = [1, 10, 20, 15, 25, 5];
arr.sort(function(value1, value2){
return value1 - value2;// return value2 - value1;//从大到小
}) ;//从小到大排序
alert(arr);
升序:
var arr = [1, 10, 20, 15, 25, 5];
arr.sort(function(value1,value2){
if(value1>value2){
return 1;
}
else if(value1
运行程序:
1、准备运行程序要用的空间(一旦分配好以后,内存大小没法进行改变了。)
2、开始运行程序
数组:数组的变量存储的是数组的地址
var arr1 = [10, 20, 30, 40];
var arr2 = arr1;//地址完全相同
arr2.push(50, 60);
alert(arr1); //10,20,30,40,50,60
alert(arr2); //10,20,30,40,50,60
(1)程序运行段(arr1和arr2里面存储的是数组的地址666) arr1 arr2
(2)堆(里面储存的是数据)**666:**10,20,30,40–>push–>**666:**10,20,30,40,50,60
//concat() 拷贝原数组生成一个新数组。
var arr1 = [10, 20, 30, 40];
var arr2 = arr1.concat();//值一样,但是堆的地址不一样
arr2.push(50, 60);
alert(arr1); //10,20,30,40
alert(arr2); //10,20,30,40,50,60
arr1里面地址:666 arr2地址:888
666:10,20,30,40---->拷贝生一个新的数组 888:10,20,30,40–>push–>888:10,20,30,40,50,60
内存分配,一次分配
**预编译:**将代码重头到尾看一遍,将这个程序要运行的空间一次性分配好。
alert(num);//undefined
var num=10;
alert(num);//10
show();//hello
function show(){
document.write("hello");
}
声明提升:在当前作用域,声明的变量和函数,会直接提升在整个代码的最前面运行
省略var,直接强制给一个变量赋值,这个变量会被强制转换为全局变量;
【注】不建议,属于语法错误
function show(){
num=10;
alert(num);//10
}
show();
alert(num);//10
数组存储数据,数组中每一个元素, 元素可以是任意的数据类型。
【注】数组中的元素可以是数组。
二维数组:人为起的。
var arr1 = [10, 20, 30];
var arr = [true, 100, "hello", arr1];
alert(arr.length);
alert(arr[3] == arr1);
alert(arr[3]);
alert(arr1[1]);
alert(arr[3][1]);
规则:前后两个数两两进行比较,如果符合交换条件就交换两个数位置。
规律:冒泡排序每一轮排序,都可以找出一个较大的数,放在正确的位置。
分析:
比较轮数 = 数组长度 - 1;
每一轮比较的次数 = 数组长度 - 当前的轮数。
//冒泡排序 升序
function bubbleSort(arr){
for(var i = 0; i < arr.length - 1; i++){
//每一轮比较的次数
for(var j = 0; j < arr.length - (i + 1); j++){
if(arr[j] > arr[j + 1]){//arr[j] < arr[j + 1]//降序
//交换两个数位置
var tmp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = tmp;
}
}
}
}
规则:选出一个位置,这个位置上的数,和后面所有的数进行比较,如果比较出大小就交换两个数位置。
规律:每一轮都能选出一个最小的数,放在正确的位置。
比较的轮数 = 数组长度 - 1;
每一轮比较的次数 = 数组长度 - 当前的轮数
function changeSortAsc(arr){ //升序
for(var i = 0; i < arr.length - 1; i++){
//被比较的数的下标
for(var j = i + 1; j < arr.length; j++){
if(arr[i] > arr[j]){
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
function changeSortDesc(arr){ //降序
for(var i = 0; i < arr.length - 1; i++){
//被比较的数的下标
for(var j = i + 1; j < arr.length; j++){
if(arr[i] < arr[j]){
var tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
}
}
// 数组去重
function noRepeat(arr){
for(var i = 0; i < arr.length - 1; i++){
for(var j = i + 1; j < arr.length; j++){
if(arr[i] === arr[j]){
//将后面这个数删除
arr.splice(j, 1);
j--;
}
}
}
}
严格模式:写在哪个作用域下,在哪个作用域下生效。
“use strict”
【注】尽量注意不要严格模式写在全局。
用了严格模式,会有什么好处:
1、全局变量声明时,必须加var
2、函数内重名属性
3、arguments对象不允许被动态改变
4、新增保留字:implements, interface, let, package, private, protected, public, static, yield。
<1>indexOf(data,start) O要大写用于返回某个数组或者字符串中规定字符或字符串的位置;
date红色参数为必选参数也就是必须传递的参数,start蓝色参数为非必选参数,也就是可以不传的参数;
格式:数组.index(item, start);
参数: item 任意的数据 start 下标 可以不传入,默认是0
功能:在数组中查找第一次出现item元素下标,从start开始去查找
返回值: -1 没有查找到 >=0 查找到的元素的下标。
var arr = ["a","b", "c, "d", "e", "f","g" ]
var str = 'abcdefg';
arr.indexOf('a');
第二个参数表示从该字符串的第n位开始检索
<2>forEach() 循环;
var arr = [2, 3, 4, 5, 6, 7];
arr.forEach(function(item, index, arr){
三个参数分别代表:
item 当期遍历到的元素
index 当前遍历到的下标
arr 数组本身
})
<3>map() 映射
会遍历当前数组,然后调用参数中的方法,返回当前方法的返回值;
var arr = [2, 3, 4, 5, 6, 7];
var newArr = arr.map(function(item, index, arr){
return item + 1;
})
console.log(newArr);
//map不会改变原有数组,而是将函数执行一次之后的返回值组成一个数组,返回回来。
<4>filter() 过滤
var res = [88,69,92,77,90,96,98,99].filter(function(item, index, array){
return item>80; //找出所有大于80的元素
}); 结果:[88,92,90,96,98,99]
<5>reduce() 归并
prev 第一次是 下标为0的元素
第二次开始 上一次遍历return的值
next 从下标1开始,当前遍历到的元素
arr数组本身
var arr = [10, 20, 30, 40, 50];
var res = arr.reduce(function(prev, next, index, arr){
alert(prev + ", " + next);
return prev + next;
});
alert(res);
<6>some() 某些
【注】在数组中查找是否有符合条件的元素,有返回true,没有返回false。
短路操作:只要找到符合条件的元素,后面的循环就停止了。
if(["yt","hr","wc","jk"].some(function(item){
//判断数组中是否存在yt?
return item=="yt”;
})){
alert("好的!");
}
<7>every()
every 每一个
【注】在数组中查找每一个元素是否有符合条件,符合返回true,不符合返回false。
短路操作:只要找到不符合条件的元素,后面的循环就停止了。
跟some一样,但要求每一项都符合,才返回true 有一项不合格就返回false
<8>String的trim方法
" abc ".trim();
首尾去空格
"abc"
字符串概念:所有带单引号或者双引号的都叫做字符串。
字符串声明:
1、通过new运算符去声明字符串
2、省略new声明字符串
3、字符串常量赋值
访问字符串中的字符:
字符串.length 访问字符串中字符的个数。
【注】中文 万国码utf-8(三个字符表示一个汉字)) gbk(两个字符表示一个汉字) 在计数的时候都是当做一个汉字计数。
访问字符串中单个字符:
字符串.charAt(下标) 【注】从0开始的
字符串[下标]
【注】字符串是只读,字符串一旦被声明就没有办法被修改,如果非要声明字符串,我们只能讲原字符串效果,重新生成新的字符串。
【注】在JS中,字符串既是基本数据类型,又是复合数据类型。
charCodeAt()
格式:字符串.charCodeAt(下标)
功能:访问字符串中对应下标字符的ASCII码值。
fromCharCode();
格式:String.fromCharCode(码值1, 码值2…);
功能:将传入的ASCII码值转成对应的字符
返回值:组成的字符串
indexOf()
格式:supStr.indexOf(subStr, start);
参数:第一个参数,查找的字符串
start 从哪个下标开始去查找,如果不传入,默认从下标0开始查找
功能:在supStr中查找subStr第一次出现的位置,从start这个位置开始查找。
返回值:-1 说明没有查找到
lastIndexOf()
格式:supStr.lastIndexOf(subStr, start);
功能:在supStr中查找subStr最后一次出现的位置
参数:第二个参数是开始查找的位置,查找的下标是从右往左数的。
返回值: -1 没有查找到
search()
格式:supStr.search(subStr);
参数:字符串/正则表达式
功能:在supStr中查找subStr第一次出现的位置
返回值: -1 没有查找到
正则表达式:
修饰符: i 忽略大小写 g 全局匹配
var supStr = "Abcabcabc";
var subStr = "abc";
var subStr = /abc/i;
var index = supStr.search(subStr);
alert(index);
substring()
格式:字符串.substring(start, end);
功能:将字符串中 [start,end) 提取这部分字符,生成一个新字符串
返回值:新生成的字符串
substr()
格式:字符串.substr(start, length);
返回值:新生成的字符串
slice(是数组)
格式:字符串.slice(start, end);
replace()
格式:supStr.replace(oldStr, newStr);
功能:用newStr将oldStr,替换掉,生成新字符串。
参数:
第一个参数传入的是字符串只能替换一次。
第一个参数 正则表达式
/xxx/ig i忽略大小 g全局匹配
返回值:替换成的新字符串。
正则表达式(专门讲) super string
var str = "how are aRe are you";
var newStr = str.replace(/are/gi, "old are");
alert(newStr);
alert(str);
split() 字符串分割
格式:字符串.split(分割符, length)
参数:
第一个参数,用这个分割符对原字符串进行分割
第二个参数,控制返回的数组的元素格式,一般情况下不用。
功能:用分割符对原字符串,进行字符串分割,将分割完毕以后的子串,放在数组中返回。
返回值:数组
注意:
1、相邻的两个分割符,会产生空字符串 “”
2、分割符是空字符串"",直接将每一个字符,单独分割成子串,放在数组中返回
toLowerCase() 转成全小写
toUpperCase() 转成全大写
var str = "helloWORLD";
alert(str.toLowerCase());
alert(str.toUpperCase());
concat 字符串拼接
var str1 = "hello";
//var newStr = str1.concat("world", 100);
var newStr = str1 + "world" + 100;
alert(newStr); //helloworld100
验证码:验证你是否是机器人
纯数字组成的验证:非常容易破解 6位数字验证码
数字和字符组成的验证码:
0~9
a-z 97~122
A-Z 65~90
随机:0~122
方法:
1、生成一个数组,装有单个字符,长度62数字
随机 0~61的下标
2、随机ASCII码值
//n等于6,生成6位的验证码
//n位验证码 每一个数字的范围 0~9 Math.random()只能生成0~1的整数
function codeTest(n){
var arr=[];
for(var i = 0;i < n;i++){
var num=parseInt(Math.random() * 10);
arr.push(num);
}
return arr.join("");
}
var str=codeTest(6);
alert(str);
//生成带有数字和大小写字母的验证码
function codeTest2(n){
var arr=[];
for(var i = 0;i < n;i++){
var num=parseInt(Math.random() * 123);
if(num >= 0 && num <= 9){
arr.push(num);}
else if(num >= 65 && num <= 90|| num >=97&& num <= 122 ){
arr.push(String.fromCharCode(num));
}
else{
i--;
}
}
return arr.join("");
}
alert(codeTest2(6));
【注】通过id获取页面上对应的标签
document.getElementById(id);
node.innerHTML 标签间的内容
function btnClick(){
//拿到div这个标签
var oDiv = document.getElementById("div1");
// alert(oDiv.innerHTML); 取值
// oDiv.innerHTML = '赋值';
oDiv.innerHTML = testCode(6);
}
000000
例:敏感词过滤
表单元素,获取其中内容,通过.value的属性
双标签节点 innerHTML属性,获取标签间内容,设置标签间内容,如果文本中含有标签,会自动解析。
要求:
1、敏感词都过滤 正则表达式
2、将敏感词替换成*
replace()
var arr = [/靠/ig, /tmd/ig, /nm/ig];
function btnClick(){
var oTxt = document.getElementById("txt1");
var oMsg = document.getElementById("msg");
var oValue = oTxt.value;
for(var i = 0; i < arr.length; i++){
oValue = oValue.replace(arr[i], "*");
}
oMsg.innerHTML = oValue;
oTxt.value = '';
}
事件驱动函数 onclick onblur 失去焦点
思想:面向对象编程思想:直接将生活逻辑映射到我们的程序。
<1>分析有哪些实体
<2>设计实体属性和功能
<3>实体之间相互作用
语法:(在JavaScript中没有类这个概念,只有对象,ECMA6版新增了类的概念)
类:一类具有相同特征事物的抽象概念。
对象:具体某一个个体,唯一的实例。
类 对象
狗 你遇到的那只
电脑 你桌上那台
代码:对象的代码
数据结构: :基本数据类型(存储一个值) => 数组(处理批量的数据) => 对象(既可以存储数据又可以存储函数)
// 面向对象的编程思想
var car = {
speed: 60,
run: function(road){
return road.length / car.speed;
}
};
var changjiang=Object();
//changjiang["length"]=1000;
var changjiang={
length:1000;
}
/*
数字.toFixed(n)
保留n为小数的
*/
var hours = car.run(changjiang);
alert("一共花了" + hours.toFixed(2) + "小时");
(1)声明一个对象:
1、通过new运算符声明对象
2、通过省略new
3、对象常量赋值 (使用大括号,代表对象)
var obj1 = new Object();
var obj2 = Object();
var obj3 = {};
对象属性 普通变量
对象方法 普通函数
婚后 婚前
新增属性:obj.属性=字符串;
obj[‘属性’]=字符串;
//新增属性 使用起来和普通的变量没有任何区别
/*obj3.username = '钢铁侠';
obj3.age = 18;*/
//[]填写的必须是字符串
obj3['username'] = '钢铁侠';
obj3['age'] = 18;
obj3.show=function(){
alert("我的名字叫" + obj3.username + ",今年" + obj3.age + "岁");
}
//通过对象常量赋值,复合写法
var obj3 = {
username: "钢铁侠",
"age": 18,
show: function(){
alert("我的名字叫" + obj3.username + ",今年" + obj3.age + "岁");
}
};
/*
delete 关键字 删除对象的属性或者方法
*/
delete obj3.username;
delete obj3.show;
alert(obj3.username);//已经被删除了,undefined
obj3['show']();//函数不存在
【注】在JS中一切皆对象。
【注】在JS,很多关系数学运算的函数,直接一个Math对象提供。
【注】查阅文档。
■Math.random() //返回0-1之间的随机数
■Math.max(num1, num2) //返回较大的数
■Math.min(num1, num2) //返回较小的数
■Math.abs(num) //绝对值
■Math.round() 四舍五入(成整数,只看小数点后一位)
■Math.ceil(19.3) //向上取整
■Math.floor(11.8) //向下取整
■Math.pow(x,y) //x的y次方
■Math.sqrt(num) //开平方
传入的参数是:弧度
Math.sin() 正弦
Math.cos() 余弦
Math.PI = 180弧度
1弧度 = Math.PI / 180;
日期对象声明
1、没有传入参数,默认当前系统时间
Wed Oct 09 2019 09:06:49 GMT+0800 (中国标准时间)
GMT 格林尼治时间
2、传入参数
“2000-01-01”
“2000/01/01”
按照顺序,分别传入参数 年 月 日 时 分 秒 毫秒
【注】在国外月份是从0开始数的 0~11
直接传入毫秒数 1秒 = 1000毫秒 (已1970年1月1日 0:0:0 为参照时间点去进行换算)
小彩蛋:linux的创始人
var d = new Date("2000-01-01");
var d = new Date("2000/01/01");
var d = new Date(2000, 0, 1, 8, 30, 50);
var d = new Date();
Date.parse()
格式:Date.parse(日期对象)
功能:可以将日期对象转成毫秒数
d.getTime()/d.setTime();
格式:日期对象.getTime/setTime
功能:将当前日期对象转成毫秒数
自定义当前时间:
Document
/*
获取两个日期之间相差的天数
*/
function countOfDate(d1, d2){
var dd1 = new Date(d1);
var dd2 = new Date(d2);
var time1 = dd1.getTime();
var time2 = dd2.getTime();
var time = Math.abs(time1 - time2);
return parseInt(time / 1000 / 3600 / 24);
}
/*
输入n,输出n天后的时间。
*/
function afterOfDate(n){
var d = new Date();
var day = d.getDate();
d.setDate(day + n);
return d;
}
alert(afterOfDate(30));
浏览器的对象(模型)
提供与浏览器交互的方法和接口
window 方法 (一般情况下window可以省略)
alert() 弹出警告框
confirm() 弹出一个带确定和取消的提示框
返回值:如果点击确定,返回true
如果点击取消,返回false
prompt() 弹出一个带输入框的提示框
参数:
第一个参数:面板上显示的内容
第二个参数:输入框里面的默认(可以不传入)
返回值:点击确定,返回输入框中的内容
点击取消,返回null。
var res = confirm("你要离开吗?");
if(res==true){
alert("行");
}
else{
alert("滚吧!");
}
第一个参数:跳转的url 打开一个新窗口,加载url
第二个参数:字符串,给打开的窗口起一个名字,【注】不命名会每次打开新窗口,命名的第一次打开新窗口,之后在这个窗口中加载。
第三个参数:一串特殊含义的字符串,可以控制打开窗口的属性
function btnClick(){
// window.open()
open("https://www.baidu.com", "xxx", 'width=400,height=400,top=200,left=300,scrollbars=yes');
}
history 对象 window.history 掌管的是,当前窗口(注意不是浏览器)历史记录(只要加载url不一样就会产生历史记录)
属性
history.length 输出当前窗口历史记录的条数
方法
history.back() 返回上一条历史记录
history.forward() 前进到下一条历史记录
history.go()
参数: 0 刷新当前页面
正整数 前进n条记录
负整数 后退n条记录
url:统一资源定位符。
中文版本: 协议://主机名:端口号/路径/?查询字符串#
英文版本: protocol://hostname:port/pathname/?searchname#hash
location.protocol file:本地磁盘文件访问
http:
https:(证书认证协议)
location.hostname 主机名 IP(在全球范围内找到你当前的网址)
域名就是IP的别称
location.port 端口号(默认隐藏的
当前电脑中使用网络的软件,随机给他分配的编号 0-65535
hostname.port 可以直接定位到当前使用网络的程序
小细节:浏览器的默认端口号8080
http:80
https:443
location.pathname 路径
location.seach 查询字符串(前后端交互)
?name1=value&name2=value2
location.hash 锚点
location.hash = ‘#1’; //设置#后的字符串,并跳转
alert(location.hash);
alert(location.href); //获取当前的URL
属性:
方法:
location.assign(url)
【注】在当前窗口跳转带这个url
location.replace(url)
【注】在当前窗口替换成新的url。不会产生历史记录。
location.reload()
【注】刷新窗前窗口
location.reload(true) 不经过浏览器缓存强制从服务器重载
DOM: document object model(文档对象模型) 提供访问和操作网页内容的方法和接口
元素节点 :
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TN3GblDh-1603178349486)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\1602934723432.png)]
元素节点的获取
document.getElementById(id)
功能:通过id获取符合条件的元素,(id必须是唯一的)
返回值:就是符合条件的一个节点。
这是一个div
/*
获取行间属性的值
*/
/* alert(oDiv.id);
alert(oDiv.title);
//访问class 通过className访问
alert(oDiv.className); */
//设置行间属性的值
/* oDiv.id = "div2";
oDiv.title = 'world';
oDiv.className = 'box4'; */
/*
【注】只能访问标签行间的css样式。
*/
alert(oDiv.style.width);
alert(oDiv.style.height);
/*
【注】如果css样式带-,将-去掉,从第二个单词开始首字母大写
*/
// alert(oDiv.style.backgroundColor);
oDiv.style.backgroundColor = 'blue';
功能:从node节点开始,通过标签名获取符合条件的元素节点。
返回值:伪数组/类数组
(IE8以下不兼容)
功能:通过class名字获取符合条件的元素节点。
功能:通过name属性的值获取符合条件的元素节点。
【注】一般使用在表单元素里。
window.onload = function(){
// var aLis = document.getElementsByTagName("li");
// alert(aLis); 使用起来和数组类似,一般情况,把这种叫做伪数组/类数组(自己起)。
/* var oOl = document.getElementById("ol1")
;
var aLis = oOl.getElementsByTagName("li");
//获取ol下的li节点
alert(aLis.length);
for(var i = 0; i < aLis.length; i++){
aLis[i].style.backgroundColor = 'red';
} */
返回值:一个元素节点,找到符合条件的第一个元素节点。
返回值:返回值,是一个伪数组。
参数:字符串 CSS选择器格式字符串。
2.获取当前有效样式
通过.style.xxx的方式只能访问内联的css样式。
**例:**写一个定时器,每个一秒修改一次div内文本颜色和文字大小.最开始这个文字是默认大小,大小开始增大,当增大了6次以后, 文字大小开始缩小,缩小6次,文字再开始增大。
Document
div文本
方法将获取元素中某个属性的值。它和直接使用.属性获取属性值的方法有 一定区别。
document.getElementById('box').getAttribute('id');//获取元素的 id 值 document.getElementById('box').id; //获取元素的 id 值document.getElementById('box').getAttribute('mydiv');//获取元素的自定义属性值document.getElementById('box').mydiv; //获取元素的自定义属性值document.getElementById('box').getAttribute('class');//获取元素的 class 值document.getElementById('box').getAttribute('className');
方法将设置元素中某个属性和值。它需要接受两个参数:属性名和值。如果属性本身已存在,那么就会被覆盖。
document.getElementById('box').setAttribute('align','center');//设置属性和值document.getElementById('box').setAttribute('bbb','ccc');//设置自定义的属性和值
可以移除 HTML 属性。
document.getElementById('box').removeAttribute('style');//移除属性
用于获取当前元素节点的第一个子节点,相当于 childNodes[0];
用于获取当前元素节点的最后一个子节点,相当于 childNodes[box.childNodes.length- 1]。
alert(box.firstChild.nodeValue); //获取第一个子节点的文本内容
alert(box.lastChild.nodeValue); //获取最后一个子节点的文本内容
属性可以获取某一个元素节点的所有子节点,这些子节点包含元素子节点 和文本子节点。
//PS:使用 childNodes[n]返回子节点对象的时候,有可能返回的是元素子节点,比如 HTMLElement;也有可能返回的是文本子节点,比如 Text。元素子节点可以使用 nodeName 或者 tagName 获取标签名称,而文本子节点可以使用 nodeValue 获取。
for(vari=0;i
nodeType nodeName nodeValue
元素节点 1 标签名 null
属性节点 2 属性名 属性值
文本节点 3 #text 文本内容
var box=document.getElementById(‘box'); //获取一个元素节点
alert(box.childNodes.length); //获取这个元素节点的所有子节点
alert(box.childNodes[0]); //获取第一个子节点对象
PS:在获取到文本节点的时候,是无法使用 innerHTML 这个属性输出文本内容的。这 个非标准的属性必须在获取元素节点的时候,才能输出里面包含的文本。
alert(box.innerHTML); //innerHTML 和 nodeValue 第一个区别
PS:innerHTML 和 nodeValue 第一个区别,就是取值的。那么第二个区别就是赋值的时 候,nodeValue 会把包含在文本里的 HTML 转义成特殊字符,从而达到形成单纯文本的效果。
box.childNodes[0].nodeValue='abc';
//结果为:abc
box.innerHTML='abc';
//结果为:abc 加粗
ownerDocument //属性返回该节点的文档对象根节点,返回的对象相当于 document。
parentNode // 属性返回该节点的父节点,
previousSibling //属性返回该节点的前一个同级节点,
nextSibling //属性返回该节点的后一个同级节点。
alert(box.parentNode.nodeName); //获取父节点的标签名
alert(box.lastChild.previousSibling); //获取前一个同级节点
alert(box.firstChild.nextSibling); //获取后一个同级节点
attributes 属性返回该节点的属性节点集合。
box.attributes //NamedNodeMap
box.attributes.length; //返回属性节点个数
box.attributes[0]; //Attr,返回最后一个属性节点
box.attributes[0].nodeType; //2,节点类型
box.attributes[0].nodeValue; //属性值
box.attributes['id']; //Attr,返回属性为 id 的节点
box.attributes.getNamedItem('id'); //Attr
var body= document.getElementsByTagName('body')[0];//获取 body 元素节点alert(body.childNodes.length); //得到子节点个数,PS:在非 IE 中,标准的 DOM 具有识别空白文本节点的功能,所以在火狐浏览器是 7 个,而 IE 自动忽略了,如果要保持一致的子元素节点,需要手工忽略掉它。
方法1:
function filterSpaceNode(nodes){
var ret=[]; //新数组
for(vari=0;i
write()方法可以把任意字符串插入到文档中去。
document.write('这是一个段落!
')'; //输出任意字符串
【注】会覆盖页面上原有的内容。
格式:document.createElement()
参数:标签名
返回值:创建好的这个节点
createElement()方法可以创建一个元素节点。
document.createElement('p');
格式:node1.appendChild(node2);
功能:将node2节点插入到node1节点子节点的末尾
appendChild()方法将一个新节点添加到某个节点的子节点列表的末尾上。
var box=document.getElementById(‘box’); //获取某一个元素节点
var p=document.createElement('p'); //创建一个新元素节点
box.appendChild(p); //把新元素节点
添加子节点末尾
格式:document.createTextNode(文本);
功能:创建文本节点(纯文本)
createTextNode()方法创建一个文本节点。
var text =document.createTextNode('段落'); //创建一个文本节点
p.appendChild(text); //将文本节点添加到子节点末尾
格式:box1.parentNode.insertBefore(box2, box1);
功能:将box2添加到box1的前面
insertBefore()方法可以把节点创建到指定节点的前面。
box.parentNode.insertBefore(p,box); //把之前创建一个节点
PS:insertBefore()方法可以给当前元素的前面创建一个节点,但却没有提供给当前元素 的后面创建一个节点。那么,我们可以用已有的知识创建一个 insertAfter()函数。
replaceChild()
格式:box1.parentNode.replaceChild(box2, box1);
功能:用box2节点将box1节点替换掉。
box.parentNode.replaceChild(p,box); //把换成了
cloneNode()
格式:node.cloneNode()
格式2:node.cloneNode(true); 克隆节点本身和子节点
返回值:克隆出来的新节点
cloneNode()方法可以把子节点复制出来。
var box=document.getElementById('box');
var clone=box.firstChild.cloneNode(true); //获取第一个子节点,true 表示复制内容 ,false表示只赋值标签
box.appendChild(clone); //添加到子节点列表末尾
removeChild()
格式:box.parentNode.removeChild(box);
功能:将box节点从页面上删除
box.parentNode.removeChild(box); //删除指定节点
14.this关键字
如果我们使用person.firstName和person.lastName,某些情况下代码会变得模棱两可。例如,全局变量中有一个跟person同名的变量名。这种情况下,如果我们想要读取person.firstName的值,系统将有可能从全局变量的person变量中读取firstName属性(property)。这样一来,我们调试代码的时候很难发现错误。所以this并不只起到美化代码的作用,同时也是为了保证程序的准确性。
this概念:只要封装函数,任何一个函数系统都会内置一个叫做this的变量,
this变量存储的是地址,是当前函数主人的地址。
【注】this永远指向当前函数的主人。函数的主人要通过当前上下文去判断。
this类似于现实生活中,用到的"我"。
this方法:如果一个方法内部使用了this关键字,仅当对象调用该方法时this关键字才会被赋值。我们估且把使用了this关键字的方法称为“this方法”。
var person = {
username: "钢铁侠",
sex: "男",
show: function(){
alert(this.username);
}
};
person.show();//钢铁侠
function show1(){
alert(this);//指向window对象
}
show1();
window.show1();
15.offset方法
offsetWidth
offsetHeight
offsetLeft
offsetTop
alert(getStyle(oDiv, "width"));//100
alert(oDiv.offsetWidth); //width(100) + border(2) + padding(8) (眼睛能看到的实际的宽)118
alert(oDiv2.offsetLeft); //眼睛能看到实际距离第一个有定位的父节点的距离。
alert(getStyle(oDiv2, "left")); //auto
事件:
事件:事件是发生并得到处理的操作,即:事情来了,然后处理。
绑定事件方式:
1、内联模式
2、外联模式/脚本模式(最多)
绑定事件格式:
元素节点.on + 事件类型 = 匿名函数。
click 事件类型
onclick 事件处理的函数
1.事件类型的种类:
鼠标事件(可以绑定在任意的元素节点上)
click 单击
dblclick 双击
mouseover 鼠标移入
mouseout 鼠标移出
mousemove 鼠标移动(会不停的触发)
mousedown 鼠标按下
mouseup 鼠标抬起
mouseenter 鼠标移入
mouseleave 鼠标移出
键盘事件(表单元素,全局window)
keydown 键盘按下(如果按下不放手,会一直触发)
keyup 键盘抬起
keypress 键盘按下(只支持字符键,不支持功能键)
window.onload = function(){
var i = 0;
/* window.onkeydown = function(){
document.title = i++;
}; */
window.onkeypress = function(){
document.title = i++;//修改标题
};
window.onkeyup = function(){
document.title = '抬起'
}
}
HTML事件
1、window事件
load 当页面加载完成以后会触发
unload 当页面解构的时候触发(刷新页面,关闭当前页面) IE浏览器兼容
scroll 页面滚动
resize 窗口大小发生变化的时候触发
load:当页面完全加载后在 window 上面触发,或当框架集加载完毕后在框架集上触发。
window.onload=function() { alert('Lee'); };
2、表单事件
blur 失去焦点
focus 获取焦点
select 当我们在输入框内选中文本的时候触发
change 当我们对输入框的文本进行修改并且失去焦点的时候
【注】必须添加在form元素上
submit 当我们点击submit上的按钮才能触发
reset 当我们点击reset上的按钮才能触发
2.事件对象
事件绑定:
元素节点.on + 事件类型 = 匿名函数;
【注】系统会在事件绑定一旦完成的时候,生成一个事件对象。
【注】触发事件的时候,系统会自动去调用事件绑定的函数。将事件对象当做第一个参数传入。
var show = function (ev){
// alert(ev); //这种通过形参拿事件对象的方式在IE8以下不兼容。 IE8以下 window.event;
var e = ev || window.event;
alert(e);//[object MouseEvent]
alert("hello world");
)};
window.onload = function(){
var oBtn = document.getElementById("btn1");
oBtn.onclick = show;
}
ev = ev || event 获取事件对象
event是事件对象(也是window的属性),但不是标准的,只有IE支持。
在W3C标准支持的浏览器下事件对象是引发事件函数的第一个参数,参数名随意。
function (ev){
var ev = ev || window.event;
}
而 || 的两边是不能反过来写的,||返回第一个Boolean类型为true的值,在IE中执行var oEvent = ev || event;时,ev为undefined,即为false,而event为true。所以返回的是它所支持的event。在其他浏览器中,第一个ev为true,直接返回,不用理会后面的event。而反过来写,var oEvent = event || ev;IE下不会报错,直接返回第一个为true的event但在其他浏览器中,event没有被定义,直接报错。
鼠标事件对象的属性:
button 的属性:
0 左键
1 滚轮
2 右键
获取当前鼠标位置:(原点位置不一样)
clientX clientY 原点位置:可视窗口的左上角为原点
pageX pageY 原点位置:整个页面的左上角(包含滚出去的滚动距离)
screenX screenY 原点位置:电脑屏幕的左上角
document.onmousedown = function(ev){
var e = ev || window.event;
//alert(e.button);//0 左键 1 滚轮 2 右键
alert(e.clientX + ", " + e.clientY);
// alert(e.pageX + "," + e.pageY);
alert(e.screenX + ", " + e.screenY);
}
}
事件对象的三个修改键:
shiftKey 如果按下shift键,值就是true,否则是false
ctrlKey
altKey
window.onload = function(){
document.onmousedown = function(ev){
var e = ev || window.event;
var arr = [];
if(e.shiftKey){
// arr.push("shift");
alert('shift');
}
if(e.ctrlKey){
arr.push("ctrl");
}
if(e.altKey){
arr.push('altKey');
}
if(e.metaKey){
arr.push("windows");
}
alert(arr);
}
}
键盘对象的属性:
键码:
只在keydown下支持。
【注】不管是在大写字母还是小写字母的情况下,返回的统一都是大写字母的ASIIC码值。
keyCode
which
window.onload = function(){
window.onkeydown = function(ev){
var e = ev || window.event;
var which = e.keyCode || e.which;
alert(e.which); //回车=13
};
字符码:
只在keypress下支持,只能按字符键才可以显示这个键的ASCII码值
【注】区分大小写,并且按下的时候我当前按下这个键的ASCII码值。
【注】
charCode
which
window.onkeypress = function(ev){
var e = ev || window.event;
var which = e.charCode || e.which;
alert(which);
}
目标对象:
target 目标对象/触发对象 事件对象的属性
【注】这个事件是由谁而起的。
IE8以下不兼容 window.event.srcElement;
this 永远指向当前函数的主人。
浏览器上事件天生的一个特点:事件流
事件冒泡:由里向外逐级触发。
事件捕获:由外向里逐级触发。
阻止事件冒泡:浏览器兼容问题
事件对象的属性和方法:
cancelBubble=true stopPropagation()
window.onload = function(){
var aDivs = document.getElementsByTagName("div");
for(var i = 0; i < aDivs.length; i++){
aDivs[i].onclick = function(ev){
var e = ev || window.event;
alert(this.id);
e.cancelBubble = true; //e.stopPropagation();
}
}
例一:更随鼠标一串的效果:
例二:阻止右键弹出
例三:阻止超链接的默认行为:
1、简陋的阻止a链接默认行为的方式
缺点:运行到了return,后续的内容我们就执行不到了。
2、规范的方法
e.preventDefault(); W3C
window.event.returnValue = false; 低版本IE浏览器
window.onload = function(){
var a1 = document.getElementById("a1");
// a1.onclick = function(){
// return confirm("你确定要离开当前页面么?");
// } ;
a1.onclick = function(ev){
var e = ev || window.event;
preDef(e);
alert("后续的操作");
}
};
/*
编写一个跨浏览器阻止超链接默认行为的函数
*/
function preDef(e){
if(e.preventDefault){
e.preventDefault();
}else{
window.event.returnValue = false;
}
}
例四:拖拽
拖拽:(拖拽的三剑客) 伪代码(代码草稿)
mousedown
记录鼠标按下位置和被拖拽物体相对距离
var offsetX = e.clientX - node.offsetLeft;
var offsetY = e.clientY - node.offsetTop;
mousemove
一致保持,相对距离
node.style.left = e.clientX - offsetX + ‘px’;
node.style.top = e.clientY - offsetY + ‘px’;
mouseup
取消拖拽
function limitDrag(node){
node.onmousedown = function(ev){
var e = ev || window.event;
//记录鼠标和被拖拽物体相对位置
var offsetX = e.clientX - node.offsetLeft;
var offsetY = e.clientY - node.offsetTop;
//被拖拽物体保持相对距离和鼠标移动
document.onmousemove = function(ev){
var e = ev || window.event;
var l = e.clientX - offsetX;
var t = e.clientY - offsetY;
//限制出界
if(l <= 0){
l = 0;
}
var windowWidth = document.documentElement.clientWidth || document.body.clientWidth;
if(l >= windowWidth - node.offsetWidth){
l = windowWidth - node.offsetWidth;
}
if(t <= 0){
t = 0;
}
var windowHeight = document.documentElement.clientHeight || document.body.clientHeight;
if(t >= windowHeight - node.offsetHeight){
t = windowHeight - node.offsetHeight;
}
node.style.left = l + 'px';
node.style.top = t + 'px';
}
};
//取消拖拽
document.onmouseup = function(){
document.onmousemove = null;
}
}