一、介绍
1.运行在客户端的的脚本语言。(即自己电脑,不同与在远程服务器;脚本语言逐行执行)
2.作用:表单动态校验,网页特效,服务端开发Node.js,桌面程序,App,控制硬件-物联网,游戏开发。
3.执行过程:浏览器(有渲染引擎)本身不执行JS代码,是通过JS引擎逐条翻译并执行。
4.组成:由ECMAScript(JS语法),DOM(页面文档对象模型),BOM(浏览器对象模型)组成。(后两个属于API):
ECMAScript是ECMA国际进行标准化的编程语言,规定JS语法标准。
DOM是对页面元素各种操作。
BOM对浏览器窗口的操作。
5.书写位置:
行内 <input type="button" value="唐伯虎" οnclick="alert('秋香姐')">事件属性on开头
内嵌 <script></script>
外部 <script src="./02-my.js"></script> ><中间不允许写代码
6.书写规范:HTML双引号,JS单引号。
7.注释//单行注释ctrl+/;/**/多行注释shift+alt+a
修改快捷键:设置->键盘快捷键方式->搜原默认->修改ctrl+shift+/
8.基本功能
1.输入prompt('请输入。。'); 弹出输入框用户输
2.输出alert('hh'+name); 弹出警示框,name为变量名
3.输出console.log(number); 控制台输出
9.基础知识
1.变量
1.作用:容器,是在内存存数据的空间。由空间和变量名组成。可打印验证作用。
2.初始化:var age=18; 声明(得空间和变量名)+赋值,非数字用'XX'
3.扩展:
1.更新变量:重新赋值,以最新赋值为准。
2.声明多个变量,隔开
var myname='旗木卡卡西',
age=30,
address='火影村';
3.只声明不赋值undefine;不声明不赋值用 报错;不声明只赋值√
4.命名规范:字母数字_$,不能数字开头,区分大小写,驼峰命名,尽量不用name和关键字保留字。有道,爱词霸。有波浪线说明有误。
每行代码思路最好先翻汉字。
*.Diagram Designer画图软件
2.数据类型
1.分类
按搜需内存大小不同分为不同数据类型,但JS是动态数据类型var可直接解决
简单数据类型:
1.Number数字型:含整数和浮点数,0
=0..八进制0x..十六进制 输出默认转换成十进制
1.数字型最大值Number未定义console.log(Number.MAX_VALUE);
2.无穷大Infinity;
3.无穷小-Infinity小于任何值;
alert(Infinity/Number.MAX_VALUE*2);
4.NaN非数值console.log('pink'-100);
5.console.log(isNaN())不是数字返true,⭐12/'12'/"12"都是false
但实际加引号是字符串型。
6.特殊运算
1.Number型+Boolean型:算术运算true看成1,false看成0
2.Number型+String型:变成String型拼接字符串。
3.只声明不赋值:undefined
4.Number型+undefined:NaN
5.Number型+null:Number型本身
2.Boolean布尔型,false
⭐参与数值加法运算时当1看,打印true+1为2;false0
console.log(true + 1); // 2
3.String字符串型,"" str.length
最好单引,外双内单外单内双;换行引号里面\n;\t缩进;\b空格。
检测字符串长度:打印str.length,str是变量名;空格是个字符
字符串拼接:'a'+1+age为字符串;+操作:数值相加字符相连。
任何东西和字符串拼接结果都为字符串。
4.Undefined,undefined没给值
var age;未赋值/=undefined;输出age为undefined
和数字相加为(非数字)NaN
5.Null,null
console.log(null + 1); // 1+null为1,代表啥也没有此处直接忽略
2.typeof获取数据类型
console.log(typeof num); null类型结果是object
数字在浏览器颜色不同类型不同。prompt取的是string,不能直接数相加
Number和Boolean和NaN紫色,string白色,undefined和null灰色
*.字面量:看到这个值就知道属于哪种数据类型
3.转换数据类型
解决prompt获取的数据是string,不能直接和number相加运算的问题。
1.分类
1.转为string型
打印 num.toString()
打印 String(num) *
打印 num+'' // 隐式转换
2.转为number型
1.打印 parseInt('12'); //小数部分和单位直接舍去,(JS动画)
开头必须是数字否则输出NaN
2.打印 parseFloat('12.0'); //单位直接舍去,(JS动画)
开头必须是数字否则输出NaN
3.打印 Number('12');
4.打印 '12'-0 '12'*1 '12'/1 // ⭐隐式转换减乘除Number
比较除了===暂时把string型看成number型直接判断,不用转
'123'+'120'为'123120';'123'-'120'为3
3.转为Boolen型
Boolean('12'或'true'..)
// 空和否定值转false,其他true:'';0;NaN;undefined;null
3.运算符
运算符左右最好加空格/JS-CSS-HTML Formatter插件
1.算术运算符:+-*/%
1.浮点数在算数运算中因为二进制转换会出现问题,尽量避免小数直接运算。
0.1+0.2!=0.3 因此不要直接判断浮点数是否相等
2.判断整除用%判结果是否为0(闰年)
3.优先级
*.表达式:由数字或变量或运算符组成的式子。1+1
*.返回值:表达式最终都会有一个结果返回给我们。
2.递增递减运算符:++ --
和变量搭配使用。
前置:先自加再返回值 c++目前讨论=11,(c后必加上=12)
后置:先返回原值后自加
3.比较运算符< > <= >= == != ===
结果为Boolean ⭐18=='18' >= <= > <比较时能转则默认暂时转换成Number
4.逻辑运算符&& || !
1.结果为Boolean,但⭐短路运算时不一定是Boolean类型,多个条件判断.
2.&&:全true才为true
||:有true就为true
3.⭐短路运算:&&如果表1true返表2,否则返表1;即返回最先决定整个式子真假的表达式或值(数值原样返回,简单数值计算计算,其他复杂表达式才返回true或false)
如:打印 123&&456 为456;1+2||0 为3 *.false5个值
num==0
5.赋值运算符= += -= *= /= %=
num=num+1; num++;
num=num+2; num+=2;
6.运算符优先级
一元运算符:!num num++
二元运算符:num+1
() > 一元 > 算数 > 比较 > 逻辑(&&>||) > 赋值 > 逗号
分析长代码先根据&&||划分几个模块后,每个模块由内到外判断,注意逻辑短路
二、流程控制
控制代码执行顺序。
1.顺序结构
按代码顺序依次执行。
2.分支结构
不同条件执行不同路径,得到不同结果。(根据现有条件从多种所有条件选一条符合路径)
1.if 最多只有一句会执行,一般最后一个else无()
if(){},if(){}else{},if(){}else if(){}..else{}
if(条件表达式){
()条件表达式的结果:逢真执行,逢假跳过{}内语句
}
*.判prompt的age还是string,但>=时暂时当成Number型比较了。
多分支是先看表1,不满足才能看表2,但还是多选一。写条件时满足小范围到大范围写可以通过多分支简化判断条件。(根据分数判断等级由大到小判断最合适。)
2.switch 分支少时if更好,否则switch好,===
针对特定值的判断,实现多选一,少break时可以执行不同case语句。不能判范围
switch(表达式){⭐表达式通常是变量,值必须和case值===
case value值1:
表达式和value1相等时的执行语句;
⭐break;
default:
XXXX;
}
⭐不逐条判断,表达式值和哪个匹配直接跳转,执行效率高。
3.三元表达式 ?: 条件表达式?表达式1:表达式2
二选一,条件真返回表1值,否则返回表2值。⭐可以把整个结果赋给一个变量。
3.循环结构
批量生成导航栏等。
循环体+终止条件;重复执行的某些代码通常和计数有关
1.for循环
1.for(初始变量1;条件表达式2;操作表达式3){
循环体4;
}
1.初始化变量是var声明的普通变量,通常作为计数器使用。
2.条件表达式用于决定执行多久
3.操作表达式是每次循环最后执行的代码,用于对计数器变量进行更新。
2.执行过程
1243-243-243...
3.条件表达式数值部分可以用变量表示,方便用户提供或修改。
for循环可执行规定次数相同的代码
for循环可输出不同的代码(计数器变量i)
for循环可执行规定次的重复操作(+-...100次)累加后处理数据。注意数据类型转换。
for循环打印三角阵可规律变量改到fod的初始值或条件结束值
*.断点调试执行过程
Source-代码左侧行号-刷新-鼠标可以放在测试断点的变量上
循环嵌套:拆,找和计数器类相关的规律
2.while循环
while(条件表达式){
满足就执行,只有表达式值为false才能退出该循环;
所以里面应该也有初始化变量,操作表达式来进行计数器的更新。
}
隐含if的循环,⭐{}一定要自增类更新计数器。判断输入时判断条件
3.do while循环
do{
循环体;
}while(条件表达式)
执行思路和while不同是先执行循环体再判断,为真继续执行循环体否则退出循环。
和while一样循环体部分一定要自增等更新计数器。
至少执行一次,while只有一次不执行的才和do while结果不一致
计数相关for,条件判断while。
4.break和continue区别
continue:立即跳出当前次的循环并进行下一次循环。使代码避开少一次(筛掉)
break直接终止本次整个循环。使代码满足某个附加条件后直接终止(直到。。)
三、命名规范
1.标识符
1.变量名,函数名,要有意义
2.变量名一般为名词sum,函数名一般为动词getsum
2.操作符空格
1.操作符左右要有一个空格= == < (i++无空格)
;后有一个空格
3.单行注释空格
//的后面要有一个空格
4.其他空格
if和for()外的左右两侧要有一个空格
⭐个位为3的数:num%10==3
四、数组(增删改查)
把一组数据存在单个变量名下(不同于字符串str+=的是:存好的变量某个值可以修改).
1.创建数组
1.利用new创建数组
var array=new Array(); //和对象相关,A大写,用new实际是调用构造函数?
2.利用数组字面量创建数组(常用)
var array=[]; //[]内可直接给值
数组里面的数据称为数组元素,不用数据类型统一,元素间逗号隔开。
2.获取数组中的元素
数组名[索引号];
索引号从0开始,超出长度会undfined(因为没有具体数据,未定义该元素的类型)
3.对数组遍历
遍历:把数组中每个元素从头到尾访问一次。
1.因为数组索引号从0开始,所以循环计数器的i从0开始。
2.输出的时候,arr[i]中i计数器当索引号来用
3.查询全部数组结合for循环,条件判断值<=数组个数-1;
4.arr[i]
⭐数组名命名为name会出错,命名时需避开。
4.数组长度.length
数组名.length
1.数组的长度是元素的个数,不要和索引号混淆。
2.arr.length动态检测数组的元素个数。
1.求数组和及平均值时,sum加的是数组元素arr[i],不是计数器i。
输出多个变量,逗号分隔。
2.求数组最大值:max初始值为数组第一个元素,遍历这个数组从第二个元素开始和max比较,比max大的话,把元素值赋给max。
Diagram Designer画图工具
3.数组转换为分割字符串|:和求数组和相似,连完一次再分割一次就可以。
注意i是计数器,相连量的是数组元素arr[i]
5.增加数组元素
1.通过修改length增加数组元素
length是可读写的。arr.length=5;
检查arr时控制台一行输出:tab+刷新/直接刷新
只增加数组长度没有赋具体值时,查询该位置元素结果还是undefined
2.通过索引号追加数组长度
arr[3]=5; // 索引号3对应位置原有具体元素会替换,没有具体元素会追加
arr='hihi'; //给整个数组重新赋值,整个数组元素会全部按新的长度,元素替换
所以一般不要给整个数组名直接赋值,否则数组中源数据会全部被覆盖。
空数组有规律的话可以用索引号i和arr[i]关系写for循环,注意索引0开始。
3.筛选一组数组中>=10的数赋给新的数组
法1:遍历原数组,如果arr[i]>=10,赋给新数组,循环内部新数组newArr[j]的j=0并自增。
法2:j用newArr.length替代,并且不用再自增。
4.删除指定的数组元素并赋给新数组
同3方法,更换条件为arr[i]!=0{}即可。
5.翻转数组放到新数组里
遍历时让newArr[newArr.length]=arr[i];i从arr.length-1到0(考虑newArr.length=0时对应的i写代码)
6.冒泡排序
算法,按一定顺序从小到大或从大到小排序。
一次比较两个元素,顺序错误就交换位置(用temp交换)
举个具体简单的例子,画中间过程图,分析一共趟数和每一趟次数,找规律12345->54321
五、函数
封装了一段可以被重复调用执行的代码块。让大量代码重复使用。
如求1-100和和1-50和纯for循环需要把循环写两遍,重复率高,不如把for循环步骤封装
1.语法
声明函数+调用函数。
1.声明函数:
1.function 函数名(){}命名函数 //函数名();
2.var 变量名=function(){}匿名函数 //变量名();
1.声明时:变量用var,函数用function小写;
2.函数是做某件事,函数名是动词。
3.函数不调用自己不执行
2.调用函数:函数名();
2.函数的封装思想
把一个或多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口。
3.形参实参传递过程
1.函数可以重复相同的代码:无参函数被重复调用
函数也可以重复不同的代码:根据传入的参数来调用
2.function(形参1,形参2...){} //1 形参类似局部变量,形参不用var等声明
函数名(实参1,实参2...); //2
3.传递过程
因为函数不调用自己不执行,所以上方1部分先略过;
函数调用(2)后,再回头找函数声明;调用时把实参传递给形参。
注意:多个参数间逗号隔开;形参可看作不用声明的变量
4.函数形参实参不匹配的问题
1.如果实参个数>形参个数:取到形参的个数,多余实参不看。
2.如果实参个数<形参个数:形参看作不需声明的变量,有未赋值的是undefined;undefined+数字=NaN非数字
尽量让实参和形参匹配。
4.使用函数返回值
把输出语句写到函数内部不太合理,应该把结果返回给调用者。
返回值在调用函数时用一个声明了的变量接收返回值。var food = cook('大肘子');
function 函数名(){需要返回的函数值} 返回给调用者:函数名();
函数只是实现某种功能,最终的结果需要返回给调用者。
实际开发里面,经常有一个变量来接受函数的返回结果。
⭐函数返回值
1.return除了返回函数值之外有终止函数的作用,return之后的代码不会再执行
2.return只能返回一个值,当写return多个值,每个值间逗号隔开时返回最后一个值
如果一定要return多个值可以返回一个数组(或对象)
3.函数如果没有return返回的是undefined
4.break;continue;return区别
break:结束当前循环(for,while)
continue:跳过本次循环(for,while)
return:可以跳出循环或函数,并且可以给出一个返回值,调用时相当于赋值
5.arguments获取函数的参数
当不确定有多少个参数传进来,用arguments获取参数。
它是当前函数的一个内置对象,存储了传入的所有实参到伪数组。
不用写形参,直接函数内部用arguments接收所有实参到伪数组console.log(arguments);
⭐伪数组:不是真正意义的数组:
1.具有数组的length属性
2.按照索引的方式进行存储
3.没有真正数组的一些方法pop() push()
⭐只有函数有arguments对象,而且每个函数都内置好了arguments对象
reverse翻转 sort排序
*.是返回true,不是返false
6.函数两种声明方式
1.利用关键字自定义函数(命名函数)
function fn(){}
2.函数表达式声明函数(匿名函数)
var fn=function(){}; // 最好加分号,两个fn一个是函数名一个是变量名
var 变量名=function(){}; // fun是变量名,这个函数没有函数名。(匿名函数)
1.函数表达式声明函数和声明变量差不多
2.声明变量var a存的是值,声明函数2var fn..存的是函数,调用变量名();
3.也可以传递参数
五、JS作用域
限定这个名字的可用性的代码范围。提高程序可靠性,减少命名冲突。
use strict可以将不严谨代码转换为错误。
1.分类
es6前,JS作用域:全局作用域,局部作用域。
1.全局作用域:整个script标签/单独的js文件。
2.局部作用域(函数作用域):在函数内部的,这个代码的名字只在函数内部起作用。
2.全局变量和局部变量
根据作用于的不同,分为全局变量和局部变量。
1.全局变量:在全局作用域下的变量⭐或在函数内部没有声明直接复杂的变量(不建议用),任何情况下都可使用。
2.局部变量:在局部作用域下的变量⭐或函数的形参,只能在函数内部使用。
3.执行效率区别:
1.全局变量关闭浏览器才会被销毁,比较占内存资源。
2.局部变量代码块结束后就会被销毁,比较节省内存资源。
⭐现阶段JS没有块级作用域(es6有)
块级作用域:{}内的变量 for{} if{}
3.在作用域链中查找变量值
只要是代码就至少有一个作用域;写在函数内部的是局部作用域;如果函数中还有函数就可以在作用域中又诞生一个作用域。
根据内部函数可以访问外部函数变量的机制,内层有未定义在内层的变量,变量值就近原则。(采用链式查找的方式决定取哪个值,这种方式叫作用域链)
除了看代码也可以画图,最外层是0级链。/站在目标出发,一层层往外找函数和变量名
六、JS预解析
log(num) //未定义和声明,会报错
log(num) //在后面定义和声明,undefined
fn();写在function fn(){}前 //正常使用
fun();写在var fun=function(){}前 //报错
jS引擎运行分为两步:预解析+代码执行。
1.预解析:把所有var和function提升到当前作用域的最前面。
2.代码执行:按代码书写顺序从上往下执行。
预解析分为:变量预解析(变量提升),函数预解析(函数提升)
1.变量预解析
把所有变量声明提升到当前作用域最前面,只提升声明不提升赋值。
2.函数预解析
把所有的函数声明提升到当前作用域的最前面,不调用函数。
⭐把function XX(){XX}全部提升,表达式赋值方式的函数声明不能提升。
⭐var a=9,b=9,c=9;是集体声明;var a=b=c=9;是只声明a
七、JS对象
一个具体的事物:这个苹果;一个数据库;一张网页;一个与远程服务器的连接。。
1.JS中,对象是一组无序的相关属性和方法的集合。所有的事物都是对象:字符串,数值,数组,函数。。。
1.属性:事物的特征(常用名词)
2.方法:事物的行为(常用动词)
2.作用
保存一个值用变量。
保存多个值(一组值)用数组。
保存一个人的所有个人信息用对象。(若放数组不知道这组数据具体含义)
person.age=18;。。。
1.现阶段创建对象三种方式
1.利用字面量创建对象 var 对象名={:,:匿}; //对象名.方法变量名(参数)/属性名/['属性名'];
var person={
name:'张三',
sayHi:function(){
console.log('hihi');
}
};
注意:
1.里面属性或方法采取键值对的形式。属性名:属性值
2.多个属性或方法中间用逗号隔开
3.方法:匿名函数
4.使用对象
1.使用对象的属性:
对象名.属性名/对象名['属性名']
person.name;
person['age'];
2.使用对象的方法:
对象名.方法名()
person.sayHi();
*.变量属性函数方法区别(属性和方法是写在对象里面)
1.变量和属性:都是用来保存数据的。
变量:单独声明并赋值,使用时直接写变量名(单独存在)
var num=10; num
属性:在对象里面不用声明(键值对),使用时(对象.属性)
var obj={num:18}; obj.num
2.函数和方法:都是实现某种功能。
函数:单独声明并调用,使用时函数名();
function sayHi(){}; sayHi();
方法:写在对象里面,调用时对象名.方法
var obj={sayHi:function(){}}; obj.sayHi();
2.利用new Object创建对象 var obj=new Object(=;=); 对象名.XX/XX(参);
1.利用等号赋值的方法添加对象的属性和方法。
2.追加时每个属性或方法分号结尾。
var obj = new Object(); // 创建一个空的对象
obj.name = '张三';
obj.sayHi = function () {
console.log('hi');
}
打印与之前使用方法相同。
3.利用构造函数创建对象function:对象名(){this=;this=};//new 对象(构造函数)名.XX(参)
前面两种方式一次只能创建一个对象,且代码大量重复。考虑把代码封装成一个函数增加复用性。
构造函数就是把对象里面相同的属性或方法抽象出来封装到函数里面。
function.构造函数名(){ //构造函数名首字母大写,有形参接收实参
this.属性=值/形参名;
this.方法=function(){}
};
new 构造函数名(); //调用构造函数前面多个new,调用时传实参
function Star(uname, age, sex,sang) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing=function(sang){
console.log(sang)
}
};
var ldh = new Star('ldh', 50, '男'); //该函数没有return就有返回值,已创好ldh对象,追加对象内容如new Object方法:ldh.sing()='by';//调用函数传实参
console.log(ldh);
console.log(ldh.name);
console.log(typeof ldh); //构造函数返回的是对象
1.构造函数名的首字母要大写
2.构造函数没有return就有返回结果,返回的是对象(或对象的属性方法等)
3.调用构造函数必须用new
4.只要调用一次构造函数就创建了一个对象(new Star()-->ldh{})
*.构造函数和对象
1.对象:是一个具体的事物。
2.构造函数:是一个泛指的某一大类,把对象公共属性和方式抽取出来(类似java类)
3.利用构造函数创建对象的过程叫对象的实例化。
2.new关键字
1.new 构造函数(); //在内存中创建了一个空的对象
2.this就会指向刚才创建的空对象
3.执行构造函数里面的代码,给这个空对象添加属性和方法
4.返回这个对象 //即因为new关键字的作用,不用return
3.遍历对象
对象是无序的,传统的for循环无法遍历对象属性和方法。
for...in可以对数组或对象进行循环遍历操作。for(变量 in 对象){}
for(var k in obj){
log(k); //得到属性名,长写k或key
log(obj[k]); //得到属性值⭐此时k不加引号
}
可以用此方法遍历对象属性和方法(很少遍历方法)。
对象可以让代码结构清晰;是复杂的数据类型之一;本质是一组无序的相关属性和方法的集合;构造函数泛指一大类,对象实例特指一个事物;for...in遍历对象属性和方法。
总结:1.声明对象方法:
var 对象名={属性名:'属性值',方法名:匿名函数(){}} //对象名.XX
var 变量名=new Object(属性名='属性值';方法名=匿名函数(){}); //变量名.XX
function 函数名={this.属性名=形参名;this:匿名函数(){}} //new 函数名();
对象或函数等外部追加属性或方法时,需要 对象方法名.XX
2.遍历对象for(k in o对象名){k/对象名[k]}
八、JS内置对象
JS对象分为:自定义对象,内置对象,浏览器对象(JS API)。
1.内置对象
JS自带的对象,不关心原理直接使用。
2.查阅文档
MDN,W3C
https://developer.mozilla.org
1.看该方法的功能
2.看参数的意义和类型,有[]说明[]里的参数可以没有
3.看返回值的意义和类型
4.用demo测试
3.常用内置对象
1.Math对象
1.⭐不是构造函数,不需要new调用。属性方法是静态的。但是M需要大写。(再看属性和方法)
2.自己重新封装一个Math对象
3.Math对象常用属性和方法()
Math.PI/max()/min()/floor()/ceil()/round()/random()
1.圆周率:Math.PI //3.14..
2.最大值/最小值:Math.max(1,2..) //()内不是数字时无法比较,显示NaN;没参数返回-Infinity;不用再循环了
3.绝对值Math.abs() //含隐式转换,转成Number型,('a')->NaN
4.取整 ()内隐式转换,不能转的非数值输出NaN
1.向下取整Math.floor(1.9) //1
2.向上取整Math.ceil(1.1) //2
3.四舍五入Math.round(1.6) //2
Math.round(-1.5) //-1 .5往大取
4.随机数方法random()无参
返回随机小数,[0,1);无参数;
log(Math.random());
⭐得到两个数之间的随机整数并且包含两个整数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
Math.floor(Math.random()*(max-min+1))+min
2.Date对象 (做倒计时等)
var date = new Date('2022-8-1 8:8:8')
date.getFullYear()/getMonth()/getDate()/getDay()/getHours()/getMinutes()/getSeconds()/getTime()/valueOf()
var date =+ new Date('2022,8,1')
Date.now()
是构造函数,必须用new调用对象,特指某个数组. var date=new Date();
1.常用方法
log(date);相当于new Date()无参数;返回的是当前时间。
()内参数常用写法:
2022,8,1 数字型,返回的是9月
'2022-8-1 8:8:8' 字符串型
1.var date=new Date();
1.var year=date.getFullYear();无参
2.var month=date.getMonth()+1; //0-11需月份+1
3.var d=date.getDate();
4.var day=date.getDay(); //星期是0-6 周日-周六,建个数组arr[day]
5.var h=date.getHours(); //时间<10时 '0'+时间
6.var m=date.getMinutes();
7.var s=date.getSeconds();
获取时间总的毫秒数1970.1.1-现在:使获得的时间更精确
1.date.getTime();
2.date.valueOf();
3.var date=+new Date(); //最常用
4. Date.now(); //H5新增
毫秒数是永远不重复的,是时间戳,用于说独一无二的东西或加密。
*.以上命名尽量不要和自定义明明重复,容易出问题。
倒计时:用将来的时间戳-现在的时间戳,转换JS6/10
转换:
d=parseInt(总秒数/60/60/24);
h=parseInt(总秒数/60/60%24);
m=parseInt(总秒数/60%60);
s=parseInt(总秒数%60);
输入时如果输'2022-8-1'时-旁边不要出现空格,一定要加引号。
3.Array对象
1.数组的创建
var arr={}
var arr=new Array();
//()内:1.1个数字:创建一个长度为该数字的空数组;
2.>1个数字:创建一个对应含n里面每个元素的值的数组
2.检测是否为数组
原反转数组只能得到输入内容为数组的反转,非数组返[]
直接typeof 数组名得到的是object,无法判断是否具体伪数组。
1.arr instanceof Array
obj instanceofObject...还可以用此运算符检测是否是其他类型
2.Array.isArray(参);比法1优先级更高,ie9+支持H5新增
3.增删数组元素
1.arr.push(元素,)
//末尾加1/多个元素,把1log,返回值:push完当前数组元素数,原数组变化
2.arr.pop(无参) //末尾删1个元素
3.arr.unshift() //从数组开头追加,其他一样,返回此次被删除的元素
4.arr.shift(无参) //从数组开头删除,其他一样
4.数组排序
1.arr.reverse(); //数组翻转,改变原数组,返回新数组
2.arr.sort(); //个位数数组排序,改变原数组,返回新数组
arr2.sort(function (a, b) { //arr2为对应变量名
return a - b; //b-a降序排列
})
5.获取数组索引(_方法)
已知某个元素值,查找对应索引。
1.indexOf(); //对应值最前面的索引;有返回索引号,没有返回-1
2.lastIndexOf() //对应值最后面的索引,有返回索引号,没有返回-1
两个值相同且!=-1说明只出现一次,且没有重复;===-1说明没有该元素(去重)
数组去重:遍历旧数组,拿旧数组元素查新数组有没,没有就存。
newArr.indexOf(arr[i])===-1说明新数组里没有arr[i]元素。
6.数组转化为字符串
1.arr.toString() //返回字符串,逗号分隔每一项
2.arr.join('分隔符') //返回字符串,分隔符分割每一项
7.其他
1.concat() //连接两个数组,不影响原数组,返回数组
2.slice(begin,end) //数组截取,返回被截取项目的新数组
3.splice(第几个开始,删去几个数) //返回新数组,原数组发生改变
4.String对象
str.length
//str是简单数据类型,对象等复杂数据类型才有属性和方法,此处不应该有属性
1.基本包装类型
var temp = new String('na'); // 把简单数据类型包装成复杂数据类型
var str = temp; // 把临时变量值赋给str
temp = null; // 销毁临时变量
2.字符串的不可变性
字符串被重新赋值时,原值不会被覆盖,而是开辟新内存空间存新值,并让字符串变量指向新的内存空间。
因此减少字符串重新赋值和字符串的拼接。
3.字符串常用方法
所有方法都不会修改字符串本身,操作完会返回新字符串。
1.根据字符返回位置
和数组一样
str.indexOf('某个字符',[起始位置]); //[]表示:里面内容可写可不写
str.lastIndexOf('某个字符',[]); //字符串也有类似长度和索引
2.根据位置返回字符
1.str.charAt(index) 可以遍历字符串
2.str.charCodeAt(index) //返回是字符对应的ASCII码,判断按哪个键
3.str[index] //H5新增
统计出现次数最多的字符和个数:遍历字符串:如果没,存到对象:1;有++
3.其他方法
1.concat(str1,str2...) //等效+,+更常用
2.substr(start,length) //start索引号始,取length个,重点,22年不推荐
3.slice(start,end) //从start开始截取到end,不取end(索引号)
4.substring(start,end) //和slice同,但不接受负值
5.replace('被替换的字符','替换为的字符') //一次只替第一个,不改原字符
正则表达式可以替换所有,或replace循环;用于过滤敏感词
6.split('分隔符') 把字符转为数组,识别数组每个元素间分隔符;join是把数组转为字符串
7.toUpperCase()转大写
8.toLowerCase()转小写
*.总结JS简单数据类型和复杂数据类型(内存分配和传参)
1.定义
1.简单数据类型(基本数据类型/值类型):
变量中存储的是值。
string,number,boolean,undefined,null
赋值null的对象是object;所以如果有个变量类型object值没想好,就赋null
2.复杂数据类型(引用类型):
new创的对象(系统对象,自定义对象)。
Object,Array,Date...
3.堆和栈
系统把内存分为堆和栈两大类。简单数据类型放栈,复杂数据类型放堆。
实际JS没有堆和栈的概念。
简单数据类型放栈,存的是值。
复杂数据类型放堆,栈存的是堆数据对应的地址
2.传参
值类型的变量作为实参传给函数的形参时,形参会在栈开新空间,把实参值赋给形参值中;所以形参修改不会影响到实参。
引用类型的变量作为实参传给函数的形参时,形参会在栈开新空间,把实参值赋给形参值中赋的是地址,因为两个变量指向同一个地址,所以一个参数修改会改变另一个的值。
*.Web APIS
API:预先定义的函数。
Web API:操作浏览器功能和页面元素的API(DOM,BOM)
如:alert属于浏览器接口。
---------------------------------------------------------------------------------------------------------------------------------
九、DOM
一、简介
1.Web APIs和JS关联
Web APIs是W3C标准,不再是ECScript标准,是JS独有部分,用于页面交互。
2.API和WebAPI
1.API(应用程序编程接口):预先定义的函数,是一种工具,实现想要的功能。
2.Web API浏览器提供的操作浏览器功能和页面元素的API。现阶段学的只针对浏览器做交互
*.MDN详细的API接口:https://developer.mozilla.org/zh-CN/docs/Web/API
因为Web API很多,所以这个阶段叫Web APIs。
很多都是方法(函数),有输入和输出。注意API功能,参数,返回值。
二、DOM(文档对象模型)
1.定义
处理(可扩展标记语言)HTML或XML的标准编程接口。可以通过DOM接口改变网页的内容,结构,样式。
DOM树:
1.一个页面就是一个文档document
2.页面里所有标签都是元素element
3.网页所有内容(标签,属性,文本,注释...)node
DOM把以上内容都看作对象。
2.获取页面元素element
1.根据ID获取
var element=document.getElementById('time');
1.因为现有标签才能获取,所以script标签应该写在body里的最后面。
2.document.get获得Element元素By通过Id驼峰命名法
3.id必须是大小写敏感的字符串''。
4.找到返回Element对象(完整的标签和内容),找不到返回null。 //log验证
console.dir(element);
2.根据标签名获取
document/element.getElementsByTagName('li'); //打印的marker是小圆点,可list-style:none去掉;父元素element必须指明是哪一个元素对象(伪数组形式不能作为父元素)。
1.返回的是获取元素对象(的集合),以伪数组形式存储/[]。操作元素要遍历。
2.得到的元素对象是动态的,HTML内容变时,JS不需变。
3.根据HTML5新增方法获取
1.getElementsByClassName('类名') //返回伪数组[]
2.querySelector('带符号的选择器'); //根据执行选择器返回第一个元素对象 .list
3.querySelectorAll(''); //返回所有符合的对象[]
4.特殊元素获取(body.html)
.body //无(),是对象
.documentElement; //无()
3.给元素注册事件(鼠标经过/点击/离开/键盘事件)
事件是:触发XX的响应机制。
事件组成:事件源,事件类型,事件处理程序。
1.事件源:事件被触发的对象。(谁) 触发和被触发涉及的对象都要获取。
2.事件类型:如何触发事件。
3.事件处理程序:通过一个函数赋值的方式完成。
btn.onclick = function () { //btn已获取对应具体某个元素,[]的不行
a.innerText = getDate();
}
或a.innerText = getDate(); //不需触发的不用function,元素.属性或内容等=XX
4.处理事件过程:获取事件源;注册事件(绑定事件);添事件处理程序(采取函数赋值形式)
常见鼠标事件:
4.利用DOM操作元素(改内容/属性。。)
以下都是属性:所有属性接的时候都是字符串形式。
1.改变元素内容:(可读写)
1.element.innerText=XX 不识别HTML标签;非标准;
2.element.innerHTML=XX 起到终内容,(?保留空格和换行)
获取元素内容:HTML带标签,Text去标签空格和换行
2.改变元素属性(改盒子样式4/图片地址/id)
1.imgEle.src='XX'; element.属性:获取内置属性值(本身自带的属性)
2.imgEle.setAttribute('id') element.setAttribute('属性')
关闭淘宝二维码。
循环精灵图:boxs[i].style.backgroundPositionY = index + 'px'; //style属性要加style.
3.改变表单元素属性(type,value,checked,selected,disabled)可读写
1.表单值不是innerHTML是value改;(按钮不是value是innerHTML)
this.disabled=true;
this指向的是事件函数的调用者。diaoyong.X=function(){}
一个按钮点多次问题,通过flag变量操作。点击函数放在if外,不需要循环。
2.新表单事件(后正则解决) 显示隐藏搜索框文本
onfocus
onblur
4.改变元素样式属性
1.element.style.样式 行内样式操作box.style.backgroundColor = 'purple';
1.驼峰命名无CSS的-; 2.有XX.XX.XX=' '; 3.修改为行内样式,权重高
2.循环精灵图:框不移动,图向上移动为负数。
2.element.className 类名样式操作
box.className = 'change'; //覆盖原先类名;想保留原先类名:'first change'
根据表单值的长度this.value.length
全部是可读写的。
读:元素.(style.)属性;
写:元素.(style.)属性='XXX';
*.排他思想(始终有一个元素被选中)
一组元素绑定事件,直接逐个.onclick麻烦。
for(var i=0;i<elements.length;i++){
elements[i].οnclick=function(){ //利用for逐个绑定事件
for(var j=0;j<elements.length;j++){ //先去所有背景色,先除他人再设自己
buttons[j].style,backgroundColor='';
}
this.style.backgroundColor='pink'; //script最外for先执行绑定完,只能用this
}
}
5.自定义属性操作
1.获取元素(自定义)属性值
Ele.属性
Ele.getAttribute('属性') //自定义的属性="属性值"写在HTML里,可获自定义的
2.修改元素属性值(或法2追加)
Ele.属性='属性值' //class写成className 自带
Ele.setAttribute('属性','属性值');//class特殊,写的是class不是className 自定义
3.删除元素属性值
Ele.removeAttribute('属性')
*.自定义属性的目的:保存并使用数据。有些数据可以保存到页面中不用保存到数据库中
为了避免判断不出是否是自定义属性,H5新增要求:自定义属性data-开头
H5新增的自定义属性获取方法:gA/Ele.dataset.index
dataset是一个集合,里面存放了所有以data开头的自定义属性。
1.console.log(div.getAttribute('data-list-name')); 能获取所以的
2.console.log(div.dataset.listName); dataset看成对象只能获取data-开头的,有兼容问题
3.console.log(div.dataset['listName']);看成获取对象集合的属性方法
6.操作DOM节点
利用DOM提供的方法获取元素:繁琐,逻辑不强。
利用节点层级关系获取元素:逻辑强,但兼容差。
标签,属性,文本,注释节点。
一般节点至少有.nodeType节点类型,.nodeName节点名称,nodeValue节点值。
元素节点nodeType1;属性节点2;文本节点3.主要操作的是元素节点。
1.获取节点
1.parentNode
box.parentNode;得到是离获取过的box最近的父级节点。
2.childNodes所有子节点 -> .children所有亲元素子节点
3.firstChild lastChild -> .firstElementChild .lastElementChild
找不到返null,ie9兼容问题。
console.log(ul.children[0]);
console.log(ul.children[ul.children.length - 1]);
4.nextSibling previousSibling -> .nextElementSibling .previousElementSibling
封装兼容性函数:
2.创建元素节点+添加节点(发布) 可以用来创建标签等
var li = document.createElement('li'); //创建
node.appendChild(child); //父节node里后面加元素child,相关元素先获取,类似数组push
node.insertBefore(child,指定元素的前面);//child要写前面创的对象,不能直接写对象值
3.删除节点
node.removeChild(child) //删除父元素中的子节点
*.阻止链接跳转: javascript:void(0); 或 javascript:;
4.复制节点
node.cloneNode(); //浅拷贝,只复制标签,不复制标签里面的内容。()或(false)
node.cloneNode(true) //深拷贝,复制node节点和里面的内容
5.三种动态创建元素方式
1.document.write() //当文档流加载完再用,会重绘,()创建的标签和内容
window.οnlοad=function(){}当文档流加载完再执行js
2.element.innerHTML //字符串拼接->生成放到数组
3.document.createElement()
对于JavaScript:为操作HTML,JS有了自己的一套编程接口。
对于HTML:dom使HTML形成一棵dom树:包含文档,元素,节点。
通关DOM获取的元素是一个对象。
对于元素:
1.创建
1.document.write()
2.element.innerHTML
3.document.createElement()
2.增
1.appendChild
2.insertBefore
3.删
1.removeChild
4.改
1.改属性src,href,title...
2.改普通元素内容innerHTML,innerText
3.改表单元素value,type,disabled...
4.改样式style.className
5.查dom元素
1.getElementById,getElementsByTagName(DOM提供的API方法,不推荐)
2.querySelector,querySelectorAll(H5新方法)
3.parentNode,children,previousElementSibling,nextElementSibling(节点操作)
对于属性:
1.getAttribute
2.setAttribute
3.removeAttribute
对于事件:
1.事件源.事件处理类型=事件处理程序(){}
三、事件高级
1.元素注册事件2(绑定事件)
1.传统注册方式 on开头,同一个元素同一个时间只能设置一个处理函数;否则前面被覆盖
<button οnclick="alert('hi')"></button>
btn.οnclick=function(){}
2.利用方法监听注册方式
event.addEventListener(type,listener[,useCapture])
btns[1].addEventListener('click',function(){alert('11')})
type:事件类型字符串,不带on的字符型 如:click,mouseover
listener:事件处理函数,发生该事件时,调用该监听函数
useCapture:可选参数,默认false。DOM事件流后详细。
同一个元素同一个时间能设置多个处理函数,不会被覆盖。
IE9以前:attachEvent()了解
event.attachEvent(eventNameWithOn,callback)
eventNameWithOn:事件类型带on,如:onclick,onmouseover
callback:事件处理函数
注册事件兼容性解决方案:
2.删除事件2(解绑事件)
事件默认只要触发重复执行,若再触发后不想执行,按钮可以disabled,其他元素需要解绑。
1.event.οnclick=null;
2.event.removeEventListener(type,listener[,useCapture]); //addEventListener配套
3.detach和attach配套
删除事件兼容性解决方案:
3.DOM事件流
事件发生时,在元素节点之间传播顺序。
1.捕获阶段;2.当前目标阶段;3.冒泡阶段
1,3:能接收事件,只不过不绑定事件的没有发生任何操作。(捕获:大->小,冒泡:小->大)
JS代码只能执行捕获或冒泡其中一个阶段。
onclick,attachEvent。。只能获取冒泡阶段。
addEventListener('click',function(){})可以得到捕获或冒泡。
更关注冒泡。
onblur,onfocus,onmouseenter,onmouseleave事件没有冒泡。
4.事件对象
div.οnclick=function(event){}
event是事件对象。写到侦听函数()里。当形参看。
事件对象只有有了事件才会存在。是系统自动创建的,不需要传入参数。是选择的对应事件相关的一系列相关事件信息的集合:触发的元素,鼠标点击的位置,键盘键。
event可以自己命名,如:e,evt...有兼容性问题:ie678通过window.event获取
兼容处理:
2.事件对象常见属性和方法
1.e.target
e.target和this区别:(ul>li,点li绑ul)
e.target:返回触发事件对象li;即返回被点击元素
this:返回绑定事件对象ul,冒泡原因被动触发;即返回绑定点击事件的元素
*.e.srcElement解决兼容问题:(了解)
e.currentTarget和this相似(了解),但ie678不认识,所以基本不用。
2.e.type
返回不带on的事件类型。
3.e.preventDefault()
阻止默认行为。
*.e.returnValue 非标准,ie678
return false没有兼容问题。但return后面代码不执行。只限于传统注册方式
4.e.stopPropagation()
5.阻止事件冒泡
6.事件委托(代理/委派)
7.常见鼠标键盘事件