JavaScript
JavaScript
在学习前端基础—— JavaScript 的一些笔记
JavaScript 学习
只记录与 C 语言不同的地方
输入输出
alert()——浏览器弹出警示框
console.log()——浏览器控制台打印输出信息
prompt()——弹出输入框,用户可以输入
变量
声明:var 变量名;
命名:首字母小写
数据类型
弱类型、动态类型——js 的数据类型要在初始化之后才能确定,且可变
数字前面加“0”表示是 8 进制,加“0x”表示是十六进制
数字有最大最小值:Number.MAX_VALUE|Number.MIN_VALUE
用 infinite 表示无穷大,加符号表示无穷小
NaN 表示”不是一个数字“,可以用 isNaN()来判断
字符串声明时加引号,并且注意嵌套关系
用length来求字符串的长度
转义字符写到引号里面
用 typeof 来判断数据类型
不要直接拿浮点数进行比较相等
流程控制
三元表达式:
语法:条件表达式 ? 表达式 1:表达式 2
switch 里面的判等是全等
数组
创建://两种方法
- var 数组名 = new Array();
- var 数组名 = [];
同一数组可以存放任意类型的数据类型
可以用 数组名.length 来求数组的动态长度
函数
声明:法一:关键词声明:function 函数名(形式参数) {函数体}//形参不需要声明
法二:变量声明:var 变量名 = function(){函数体};//匿名函数,调用时:变量名();
没有 return 的函数返回 undefined
用 argument(每个函数都内置有)获取用户输入的所有实参,用伪数组的形式存储
在函数内部没有声明而直接赋值的变量时全局变量
没有块级作用域——{}//括号里面的称为块级作用域
内部函数查找外部函数的变量采取链式查找的方式来决定取那个值,这种结构称为作用域链
预解析
变量提升:把所有的变量声明提升到当前作用域的最前面,但是不提升赋值操作
函数提升:把所有的(关键字的)函数声明提升到当前作用域的最前面,但是不调用函数
对象(有点像结构)
对象是一组无序的相关属性和方法的集合,比如字符串、数组、函数
创建:
用花括号创建
var obj = {};
多个属性用逗号隔开
方法(对象里面的类似于函数)后面跟的是一个匿名函数
调用对象的方法:对象名.方法名()
用 new Object 创建
- var obj = new Object();
- 用等号赋值添加属性和方法
- 用分号分开
用构造函数
- function 构造函数名(){this.属性 = 值;this.方法 = function()};
- var obj = new 构造函数名();
- 构造函数名首字母大写
- 不需要 return
遍历对象
for(var k in obj){
console.log(k);//输出属性名
console.log(obj[k]);输出属性值
}
内置对象
JS 语言自带的一些对象,供开发者使用,提供常用的功能
查文档:MDN:https://developer.mozilla.org/zh-CN/
Math 对象
不是一个构造对象,直接使用,不需要用 new 来调用
比如圆周率、自然对数等等,还有很多与 math 相关的方法,eg: Math.max();
**Math.random();**随机产生一个[0,1)之间的小数,通过一定公式也可以产生随机整数
日期对象
是一个构造函数,用 new 来调用——var date = new Date();
根据给出的参数不同,返回值不同;用不同的内置方法,获得不同的返回值
格式化:存储年月日相关信息之后,同一格式化输出
案例:倒计时
数组对象
用 new array 来创建数组
检测是否为数组:
- 用 instanceof:变量名 instanceof array //返回 true 或者 false
- 用 Array.isArray(参数)
添加或者删除数组元素:
push():添加到数组末尾
unshift():添加到数组的开头
pop():删除数组的最后一个元素
shift():删除数组的第一个元素
数组排序:
- reverse():翻转数组元素
- sort():对数组进行冒泡排序(但是直接用并不完善,还需要修正,并且同时规定排序的结果是升序还是降序)
数组索引:
indexOf(数组元素):返回数组里面第一个查找元素的索引号
lastIndexOf(数组元素):返回最后一个查找元素的索引号
数组转化为字符串:
- toString():将数组转换为字符串
- join(分隔符):自定义分隔符
字符串对象
基本包装类型:把简单数据类型包装为复杂数据类型,让其拥有一些实用的属性和方法
字符串的不可变:改变字符串的值实际上是在改变其地址,之前的值仍然存在,因此不要大量使用拼接字符
查找字符位置:
- indexOf('要查找的字符',[起始位置])//从前往后找
- lastIndexOf('要查找的字符',[起始位置])//从后往前找
根据位置返回字符:
- charAt(index):根据位置返回字符
- charCodeAt(index):根据位置返回字符的 ASCLL 码,目的:判断用户按下的那个键
- str[index]//有点类似与数组处理了
字符串操作方法:
- concat('字符串 1',‘字符串 2‘......)
- substr(‘截取的起始位置’,‘截取的字符数’)
- slice(start,end)、substring(start,end)//截取到 end 结束,end 不取,区别:substring 不接受负值
- replace('被替换的字符',‘替换成为的字符’)//只会替换第一个字符
- split('分隔符'):字符串转换为数组,其中分隔符取决于字符串所用的分隔符
简单数据类型和复杂数据类型
简单数据类型——放在栈里,存值;复杂数据类型——地址放在栈里,内容放在堆里
简单数据类型:null——返回的是一个空的对象(object)
Web APIs-BOM and DOM
详细 API:https://developer.mozilla.org/zh-CN/docs/Web/API
DOM
文档对象模型,处理可扩展标记语言的编程接口
DOM 树
文档(document):一个网页就是一个文档
元素(element):页面中的所有标签都是元素
节点(node):网页中的所有内容都是节点
DOM 可以把以上内容都看作对象
获取元素
通过 id 名字获取:document.getElementById(id)//id 是大小写敏感的字符串,所以要加‘’。
通过标签获取:
- getElementsByTagName('标签')//是字符串,也要加引号,返回获取到的元素对象的集合,都以伪数组的形式存储
- 获取父元素内部的指定标签元素:element.getElementsByTagName('标签');//父元素必须指明具体的一个对象,不会获取到父元素
通过类名获取:document.getElementByClassName('类名');//返回对象集合
document.querySelector('选择器');//根据指定选择器返回第一个元素对象,注意选择器前是否加'.'/'#'来指明是类选择器还是 id 选择器等等
document.querySelectorAll('选择器');//返回指定选择器的所有元素对象的集合
注:可以使用 console.dir 打印返回元素对象,更好的查看里面的属性和方法
获取特殊元素——body 和 HTML
- document.body //返回 body 元素对象
- document.documentElement //返回 HTML 元素对象
事件基础
事件:触发——响应机制
三要素:事件源、事件类型、事件处理程序
- 事件源:事件被触发的对象
- 事件类型:鼠标点击、鼠标经过、键盘按下
- 时间处理程序:通过赋值函数的方式
操作元素
改变元素内容(以下两个标签还可以读取元素里面的内容)
- element.innerText//不识别 HTML 标签,并且直接显示——非标准,去除空格和换行
- element.innerHTML//识别 HTML 标签,保留空格和换行
修改元素属性——src、href、id、alt、title
表单属性设置(value、type、checked、selected、disabled):表单内容通过 value 属性来修改
注:this 指向事件函数的调用者
样式属性操作:修改元素的大小、颜色、位置
- element.style.属性//行内样式操作(CSS 的权重更高),属性采用驼峰命名法
- element.className//类名样式操作,为当前元素修改类名,如果想要保留之前的类名,使用多类名选择器;减少代码量,适合于样式较多或者功能复杂的情况
排他思想:对多个同一种元素添加事件,用 for 循环,先清除所有效果,再对点击的元素添加事件
自定义属性的操作:
- 为元素添加自定义属性,并通过 element.getAttribute('属性')来获取
- 置元素的属性值:
- element.属性 = '值';//用于内置属性
- element.setAttribute('属性','值');//主要针对于自定义属性
- 移除属性:element.removeAttribute('属性');
H5 自定义属性
- 目的:为了保存并使用数据,保存在页面中而不用保存到数据库中
- 规定:自定义属性 data-开头作为属性名并且赋值,形式为 data-index
- 获取:
- element.getAttribute('data-index');
- H5 新增:element.dataset.index 或者 element.dataset['index']//dataset 是一个集合,里面存放了所有以 data 开头的自定义属性(也就是说只能获取 data 开头的);如果自定义属性里面有多个’-‘连接的单词,我们用此方法获取的时候采用驼峰命名法,eg:data-list-name 用 element.dataset.listName
节点操作
获取元素的方法
- 利用 DOM 提供的方法,也就是上文学习的方法,但是逻辑性不强,繁琐
- 利用节点层级关系获取,逻辑性强,但是兼容性稍差
节点至少拥有 nodeType(节点类型,元素节点为 1,属性节点为 2,文本节点—包括文字、空格、换行为 3)、nodeName(节点名称)、nodeVaue(节点值)
父级节点:node.parentNode//返回 node 的最近的一个父节点,如果没有就返回 null
子节点:
- parentNode.childNodes//标准,得到的是节点的所有子节点,包含元素节点和文本节点等等
- parentNode.children//非标准,得到所有子元素节点,实际开发中常用
- parentNode.firstChild//所有节点中的第一个|parentNode.firstElementChild//返回第一个子元素节点,但是有兼容性问题
- parentNode.lastChild//所有节点中的最后一个|parentNode.lastElementChild//返回最后一个子元素节点,但是有兼容性问题
- 实际开发常用:
- parentNode.children[0]//访问第一个子节点元素
- parentNode.children[parentNode.children.length - 1]
兄弟节点:
- node.nextSibling//得到下一个兄弟节点,包含元素节点和文本节点等等,找不到就返回 null
- node.previoustSibling//得到上一个兄弟节点,包含元素节点和文本节点等等,找不到就返回 null
- node.nextElementSibling//返回下一个兄弟节点,找不到就返回 null,有兼容性问题
- node.previousElementSibling//返回上一个兄弟节点,找不到就返回 null,有兼容性问题
页面中添加新的元素:
第一步——创建节点:document.createElement('tagName');//动态创建元素节点
第二步——添加节点:
- node.appendChild(child);//node-父级,child-子级,追加元素
- node.insertBefore(child,指定元素);//将节点添加到指定元素的前面
删除节点:node.removeChild(child)//删除一个子节点,返回删除节点
复制节点(克隆节点):node.cloneNode();//若括号内容为空或为 false,则是浅拷贝,只复制节点本身,不克隆里面的子节点;参数为 true,则是深度拷贝,复制节点本身以及所有子节点
注:阻止链接跳转:href='javascript:;'或者'javascript:void(0);'
- 比较动态创建元素的区别:
- document.write 是直接将内容写入页面的内容流,但是文档流执行完毕,它会导致页面全部重绘
- innerHTML 是将内容写入 DOM 节点,不会导致页面重绘
- innerHTML 创建多个元素效率更高(不是拼接字符串,而是采取数组形式拼接),结构稍微复杂
- createElement.()创建多个元素效率稍低一些,但是结构更清晰
事件高级导读
注册事件:
传统方法:用 on 开头的事件,具有唯一性,同一元素同一事件只能设置一个处理函数,最后注册的处理函数将会覆盖前面注册的处理函数
方法监听注册方式:addEventListener(),同一个元素同一个事件可以注册多个监听器,,按照注册顺序执行
eventTarget.addEventListener(type,listener,uesCapture)
type:事件类型字符串,比如 click、mouseover,参数为字符串记得加引号,且不要带 on
listener:事件处理函数,事件发生时,会调用该监听函数
useCapture:可选参数,是一个布尔值,默认为 false,用于确定监听的是捕获阶段还是冒泡阶段,默认为冒泡阶段
删除事件(解绑事件)
- 传统方式:eventTarget.onclick = null;
- 方法监听注册方式:eventTarget.removeEventListener(type,listener[,useCapture]);
DOM 事件流
事件流描述的是从页面中接受事件的顺序,事件发生时会在元素节点之间按照特定的顺序传播
三个阶段:捕获阶段、当前目标阶段、冒泡阶段(更多关注,有时会带来麻烦,有时又有妙用)
有些事件是没有冒泡的,比如:onblur、onfocus、onmousecenter、onmouseleave
事件对象:
写到监听函数的小括号里面,当作形参来看;事件对象只有有了事件才会存在,是系统自动创建的,不需要传递参数;是一系列相关数据的集合;可以自己命名,常用 event、evt、e
- 常见事件对象的常见属性和方法:
- 2e.target:返回触发事件的对象(与 this 区别,this 是返回绑定的事件
- e.type:返回事件的类型,比如:click、mouseover,不带 on
- e.preventDefaut():阻止默认事件,比如:让连接不跳转,让表单不提交
- 常见事件对象的常见属性和方法:
阻止冒泡:
- e.stopPropagation():阻止冒泡,平时主要使用
- e.cancelBubble:非标准,为 true 时阻止冒泡
事件委托(代理、委派):
- 原理:不是每个子节点单独设置事件监听器,而是事件监听器设置在其父节点上,利用冒泡原理影响设置每个子节点
常用的鼠标事件:
- 禁止鼠标右键菜单:contextmenu 主要控制应该何时显示上下文菜单(主要指右键),用于程序员取消默认的上下文菜单
- 禁止鼠标选中:selectstart-开始选中事件
- e.celentX:返回鼠标在浏览器窗口可视区域的 x 坐标
- e.celentY:返回鼠标在浏览器窗口可视区域的 y 坐标
- e.pageX:返回鼠标在文档页面的 x 坐标
- e.pageY:返回鼠标在文档页面的 y 坐标
- e.screenX:返回鼠标相对于屏幕的 x 坐标
- e.screenY:返回鼠标相对于屏幕的 y 坐标
- mousemove:鼠标移动事件
键盘事件:
onkeyup:按键弹起时触发
onkeydown:按键按下时触发
onkeypress:按键按下时触发,但是不能识别功能键,比如 ctrl、shift、左右箭头
三个事件的执行顺序:keydown->keypress->keyup
keydown 和 keypress 在文本框里面的特点:两个事件触发时,文字还没有落入文本框中;keyup 事件触发时,文字已经落入文本框了
键盘事件对象:keyCode:返回按键的 ascll 码;keyup、keydown 不区分大小写,keypress 区分大小写
BOM
BOM 概述
- 浏览器对象模型,提供独立于内容而与浏览器窗口进行交互的对象
- 顶级对象为 window,具有两重角色:
- 是 JS 访问浏览器窗口的一个接口
- 是一个全局对象。定义在全局作用域中的变量、函数都会变成 window 对象的属性和方法,在调用时可以省略 window,此前学习的对话框都属于 window 对象的方法,如 alert()、prompt()等
- 注:window 下的一个特殊属性 window.name
window 对象常见事件
窗口加载事件:
语法:window.onload = function(){}或者 window.addEventListener("load",function(){});
当文档内容完全加载完成会触发该事件(包括图像、脚本文件、CSS 文件等)
注:传统的注册事件(window.onload)方式只能写一次,如果有多个,会以最后一个为准,如果使用 addEventListener 则没有限制
语法:document.addEventListener('DOMContentLoaded',function(){})
DOMContentLoaded 事件触发时,仅当 DOM 加载完成,不包括样式表,图片,flash;Ie9 以上支持;如果页面的图片很多从用户访问到 onload 触发可能需要较长的时间,交互效果不能实现,必然影响用户体验,此时用 DOMContentLoaded 事件比较合适
调整窗口大小事件:
- 语法:window.onresize = function(){}或者 window.addEventListener("resize",function(){});
- 调整窗口大小加载事件,当触发时就调用处理函数
- 注:只要窗口大小发生像素变化,就会触发这个事件;经常利用这个事件完成响应式布局(window.innerWidth:获取当前屏幕宽度)
定时器:
window.setTimeout(调用函数,[延迟的毫秒数]);(window 可以省略,第二个参数默认为 2000ms)
用于设置一个定时器,定时器到期后执行调用函数(这种需要等待时间到了之后才执行,而不是按照代码顺序执行的函数称为回调函数 callback),且只执行一次;页面中可能有很多定时器,我们经常给定时器加标识符(名字)
window.setTimeout(timeoutID)(window 可以省略):取消了 setTimeout()建立的定时器,参数为定时器的标识符
window.setInterval(回调函数,[间隔的毫秒数]);
每隔设置的时间,就去调用一次回调函数
window.clearInterval(intervalID);:取消了 setInterval()建立的定时器
this 指向问题:一般情况下,this 的最终指向的是调用它的对象
全局作用域或者普通函数中 this 指向全局对象 window(注意定时器里面的 this 指向 window)
方法调用中谁调用了 this 就指向谁;构造函数中 this 指向构造函数的实例(var fun = new Fun();——其中 fun 就是实例对象)
JS 执行机制
- JS 之前是单线程——同一时间只能做一件事,最新的标准允许创建异步的了
- 同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的
- 异步:在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,还可以去处理其他事情。
- 同步任务:在主线程上执行,形成一个执行栈
- 异步任务:通过回调函数实现,放在任务队列中,一般分为三类:普通事件,如 click、resize;资源加载,如 load、error;定时器,包括 setInterval、setTimeout
- JS 执行机制:1、先执行执行栈中的同步任务;2、异步任务(回调函数)放在任务队列中;3、一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行
location 对象
window 对象提供的一个 location 属性,用于获取或设置窗体的 URL,并且可以解析 URL;此属性返回的是一个对象
URL:统一资源定位符,是互联网上标准资源的地址。互联网上的每个文件都有唯一的 URL,包含的信息:指出文件的位置以及浏览器应该如何处理
语法:protoool://host[:port]/path/[?query]#fragment(具体含义可以上网查找)
location 对象的属性:
location.href:获取或者设置整个 URL
location.host:返回主机(域名)
location.port:返回端口号,如果未写,返回空字符串
location.pathname:返回路径
location.search:返回参数
location.hash:返回片段,#后面内容常见于链接锚点
location 对象的方法:
location.assign():跟 href 一样,可以跳转页面(也称为重定向页面),可以后退页面
location.replace():替换当前页面,因为不记录历史,所以不能后退页面
location.reload():重新加载页面,相当于刷新按钮 f5,如果参数为 true 强制刷新 ctrl+f5
navigator 对象:包含有关浏览器的信息,常用的是 userAgent,此属性可以返回有客户机发送服务器的 user-agent 头部的值,用于判断用户是用那个终端打开的页面,实现跳转
history 对象:与浏览器历史记录进行交互。该对象包含用户(在浏览器窗口中)访问过的 URL
history 对象的方法:back():后退功能 forword():前进功能 go(参数):前进后退功能,参数为 1,前进一个页面,为-1,后退一个页面
PC 端网页特效导读
元素偏移量 offset 系列
offset:偏移量,使用 offset 相关属性可以动态的得到该元素的位置(偏移)、大小等。
获得元素距离带有定位父元素的位置;获得元素自身的大小(宽度高度);注意:返回的数值都不带单位
元素:element.offsetTop:返回元素相对于带有定位的父元素上方的偏移
element.offsetLeft:返回元素相对于带有定位父元素左边框的偏移
element.offsetWidth:返回自身包括 padding、边框、内容区的宽度
element.offsetHight:返回自身包括 padding、边框、内容区的高度
element.offsetParent:返回作为该元素带有定位的父级元素,如果父级都没有定位,则返回 body
offset 与 style 区别:
得到任意样式表中的样式值 只能得到行内样式表中的样式值
数值没有单位 得到带有单位的字符串
包含 padding、border、width 不包含 padding、border
是只读属性,只能获取不能赋值 可读写属性,可以获取也可以赋
元素的可视区 client 系列
获取元素可视区的相关信息,动态的得到元素的边框大小、元素大小
element.clientWidth:返回自身包括 padding、内容区的宽度,不含边框,返回数值不带单位
element.clientHeight:返回自身包括 padding、内容区的宽度,不含边框,返回数值不带单位
element.clientTop:返回元素上边框的大小
element.clientLeft:返回元素左边框的大小
立即执行函数:不需要调用,立马能够自己执行的函数
写法:(function() {})() 或者(function(){}());//也可以传递参数,通过后面的小括号
立即函数的最大作用就是独立创建了一个作用域,避免了命名冲突问题
元素滚动 scroll 系列:
动态获得元素的大小、滚动距离
element.scrollHeight:返回自身实际的高度(内容超出时,是内容的大小),不含边框,返回数值不带单位
element.scrollWidth:返回自身实际的宽度(内容超出时,是内容的大小),不含边框,返回数值不带单位
element.scrollTop:返回被卷去的上侧距离,返回数值不带单位
element.scrollLeft:返回被卷去的左侧距离,返回数值不带单位
onscroll 事件:滚动滚动条时会触发的事件
页面被卷去头部:通过 window.pageYOffset;卷曲左侧:window.pageXOffset
mouseenter 和 mouseover 鼠标事件:
鼠标移动到元素上时触发
区别:mouseover 是鼠标经过自身盒子会触发,经过子盒子还会出发,而 mouseenter 只有经过自身盒子触发 (原因:mouseenter 不会冒泡
跟 mouseenter 相对应的鼠标离开事件 mouseleave 同样不会冒泡
动画函数封装:
原理:通过定时器 setlnterval()不断移动盒子位置
注:元素需要加定位,才能使用 element.style.left
缓动动画:步长公式:var step = (目标值-现在的位置)/10;
step > 0?Math.ceil(step):Math.floor(step);
添加回调函数:就是将一个函数 1 当作是参数传到要调用函数 1 的函数 2 中,对于动画封装函数,要在计时器结束时调用函数 1。
节流阀:防止轮播图按钮连续点击造成播放过快;当上一个函数动画内容执行完毕,再去执行下一个函数动画,让事件无法连续触发
思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数
移动端网页特效导读
触屏事件:
概述:移动端兼容性较好,不需要考虑以前 JS 的兼容性问题
touch 事件:
touchstart:手指触摸到一个 DOM 元素时触发
touchmove:手指在一个 DOM 元素上滑动时触发
touchend:手指从一个 DOM 元素上移开时触发
触摸事件对象:
touches:正在触摸屏幕的所有手指的列表
targetTouches:正在触摸当前 DOM 元素的手指列表(最常用),targetTouches[0]就可以得到正在触摸 DOM 元素的第一个手指的相关信息,比如手指的坐标
changeTouches:手指状态发生了变化的列表,从无到有或者从有到无
classList 属性:
添加类:element.classList.add('类名');
移除类:element.classList.remove('类名');
element.classList.toggle('类名');
学习资源来自哔哩哔哩上的JavaScript 前端课程,并为全部看完,已看到 p345。