js学习小结

js

JavaScript环境

开发中的提示标签<noscript>当浏览器未开启js时, 给出的提醒</noscript>
网页嵌入js的方式
1)行内式 -->不需要重用,方法调用
2)页内式
	script标签位置问题
	1. <script>标签放在普通的标签之后  放在body底部 
	2. 耗时的js执行, 最好放在渲染之后 window.onload监听渲染事件
3)外链式

JavaScript-注释

Ctrl + /
Ctrl + Shift + /
/** + enter

注释很重要,开发成员之间的沟通,理清思路(分步骤)
js规范
https://www.cnblogs.com/polk6/p/4660195.html

JavaScript-调试

浏览器开启断点调试
	浏览器调试器中直接打断点
	代码中使用debugger

ECMAScript

浏览器支持https://www.caniuse.com/#search=es6

es5

  1. 输入输出

prompt() console.log/warn/info/error/table/dir

  1. 字面量、变量、常量

字面量就是能看到的

变量,存储字面量的,1.存储耗时长的操作结果2.抽取数据

var name = "张三";
变量命名规则: 字母 数字 _ $;不能数字开头;关键字保留字不能使用
// 变量有变量提升 相当于一开始就var name; name = "张三"
// var声明的变量为全局变量

常量,简单数据类型不能修改(大写字母),引用类型地址不变

  1. 数据类型

使用typeof检测是简单数据类型还是引用数据类型

  • 简单数据类型
    Number
    Stirng
    Boolean
    Undefined
    Null
  • 引用数据类型Object

用instanceof检测是否是某个引用数据类型

数组

对象

函数

具体的什么类型还是要看 Object.prototype.toString.call()

  1. 简单数据类型

js拥有动态的数据类型,会根据数据类型自动识别

String
var str = '张三'  建议单引号,也可以双引号,单双引号可以嵌套

转换为String类型
	1.toString() 方法 [不修改原数据,返回新数据]
	布尔类型转字符串true.toString()-->"true"
	数值类型转字符串(123).toString()-->"123" toSring(2) 转2进制
	null 和undefined没有该方法,调用报错
	2.借String 类型函数
	String(数据)
	和1的区别,null和undefined可直接转成字符串
	3.任何数据 + 字符

Number 所有数字类型
Number.MAX_VALUE,Number.MIN_VALUE
Infinity无穷大(10 / 0) -Infinity无穷小(-10 / 0) 
非法数字 NaN  isNaN()判断

JS中整数的运算可以保证精确的结果
JS中浮点数的运算可能得到一个不精确的结果
	解决方案:先升后降,先变成整数计算再把结果转换为小数
	
转化为Number类型
	1.Number(其他类型数据)
	字符串转数字,有数字转数字,空变0,有非数字变NaN true-1 false-0 null-0 undefined-NaN
	2.特殊手段: +"123" - 号 和 -0 操作  *  / 
	同Number() 函数方式
	3.parseInt()函数/parseFloat()函数
	可以提取字符串开头处的数值
	从第一位有效数字开始, 直到碰到无效数字,如果第一位不是有效数字, 直接返回NaN
	对于非String 数据转化, 会先转为String 类型后再操作-->parseFloat("true")

Boolean
关系运算符和逻辑运算符计算得出

转化为Boolean类型
	Boolean(需要转换的数据) 很少去手动转
	数值:非0 或 NaN 即真
	字符串:非''空串为真
	null 和 undefined:false

Undefined 代表变量未声明或者变量未初始化

Null 空的对象 只有一个值null 
null == undefined // true
null === undefined // false

运算符

分类 算数 关系 逻辑 typeof运算符 =赋值运算符
	单目 ++ --  双目 三目

算数运算符
	+(非stirng类型会先转换为number) - * / %
关系运算符
	> < = <= >=    == != === !==
	isNaN()方法
逻辑运算符
	&& || (返回值不一定是true或false,短路特性)
	会转换成Boolean进行判定真假,但没有改变值/表达式本身
	! (返回值一定是Boolean值)
其他
++ 和 -- 运算符 注意前后位置
?: 运算符 三目
= 赋值运算符 
	赋值运算符左边只能是变量
	多个赋值运算符可以组成 赋值表达式, 赋值表达式具备右结合性
	//  先将10赋值给变量c, 然后将变量c中存储的值赋值给变量b
	// 然后将变量b中存储的值赋值给变量a, 最后a,b,c存储的都是10
	a = b = c = 10;
复合赋值运算符 += -= *= /= %=
	赋值运算符是右结合性, 所以会先计算等号右边, 然后再进行复合运算
, 运算符
	表达式1,表达式2,… …,表达式n;
	先算表达式1,再算表达式2,依次算到表达式n,最后一个表达式的值
	使用, 运算符, 一般是为了执行多条语句, 并非是要最后结果
	变量声明,函数形参的,不是,运算符

运算优先级
() -- 一元运算 -- */% -- +- -- 移位<<>> >>> --- <><=>= --- == != 
&按位与 ^按位异或 |按位或  &&  ||  ? 赋值运算符  ,运算符
  1. 流程控制语句

    顺序
    自上而下执行,补充:代码块{}之中的代码
    分支
    单分支if(){}双分支if else多分支if elseif else
    switch(条件表达式){case 表达式;执行语句;break; default, ,break}
    case穿透问题,要加break;default位置可省,任意位置
    switch适合多个固定选项,if适合区间
    循环
    for循环
    for(①初始化表达式;②循环条件表达式;④循环后操作表达式){③执行语句;}
    for(; 😉 语句相当于while(1), 都是死循环
    while循环
    do while循环
    do { 语句1;语句2; …} while ( 条件 );
    使用场景:口令校验

    break关键字 跳出循环 多层循环时,只向外跳一层
    continue关键字 跳出本次循环

  2. 数组(Array)

有序的数据集合

创建数组的方式
	字面量创建var arr = [];
	构造函数创建
	var arr = new Array("张三","李四")
	var arr = new Array(5) 区分new Arrayof(5)  前者是length5的空数组 后者数值5的长度1的数组

常用操作
	length长度
	索引0开始
	遍历数组 forEach
	join() push() pop() shift() unshift() 
	splice(index,1,要添加进去的item)删除的索引,删除个数
	reverse() concat() 
	indexOf('a',3)从索引3开始往后找c的索引 lastIndexOf()

7.Number

paresInt() parseFloat()
isNaN()

8.String

length
indexOf(字符,start) lastIndexOf()
slice(start,end) substring(start,end)不接受负值 substr(start,legth)
replace(字符,替换字符) 可接受正则
toUpperCase() toLowerCase()
trim()
split(分割的字符)

9.Date

创建日期对象
var date = new Date()
Date.now() 返回自1970年1月1日 00:00:00 (UTC)到当前时间的毫秒
getFullYears() getMonth()注意月份是0-11 getDay() getHours() getMinutes() getSeconds()

10.Math

Math.PI
Math.round(x)四舍五入 Math.pow(x,y)x的y次幂 Math.sqrt(x)平方根 Math.abs(x)绝对值 Math.ceil(x)向上取整 Math.floor(x)向下取整  Math.min(..) Math.max(..)查找参数列表最大最小值 Math.random()取[0,1)之间随机数
  1. 函数(Function)

语法

声明
	function 函数名称(参数列表) {函数体代码}
	函数表达式声明方式  var add= function(num1){return num1;}; 
	Function构造函数 基本不用
	封装到函数中的代码不会立即执行
	调用函数 函数对象()
函数参数
	形参 实参
	解析器不检查实参的类型,开发中需要对参数进行类型检查,也不会解析参数的数量
	多余实参不会被赋值,是undefined
	arguments对象
		每个函数内置,arguments中存储传递的所有实参
		arguments是一个伪数组,因此,可以进行遍历
函数返回值(return)
	return只在函数中使用,return后续语句不会被执行
	没有return,返回undefined
匿名函数
立即执行函数
递归函数

变量作用域

作用域:变量可以被访问的范围
作用域分类
	全局作用域
		不被任何函数包裹的变量
		window的属性
	局部作用域
		多个函数嵌套, 那么这多个作用域就会形成 "作用域链"
	块级作用域
	ES5不存在块级作用域,ES6通过let/const结合{}实现块级作用域
JS Hoisting
	变量提升 提升到作用域顶部
	先 变量提升 只会将变量的声明提升
	后 函数提升 将整个函数的内容全部提升,仅限于function XX(){}类型
严格模式
	"use strict" 
	https://www.w3school.com.cn/js/js_strict.asp
变量销毁时机
	局部变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁

闭包

产生闭包的条件 1. 函数嵌套 2. 内部函数, 引用了外部函数的数据(变量)
闭包的作用
	1. 让外界访问函数内部的变量
	2. 保存循环增量值(借助闭包, 构造函数作用域)

回调函数

函数可以作为参数, 传递给另外一个函数
另一个函数在内部执行该函数

封装函数考虑因素

函数命名/函数参数/函数返回值
容错处理:参数类型处理,数值范围处理
代码逻辑
注释

12.对象

{key:value} key可以是属性也可以是方法名
js当中的对象有两种含义
	泛指一大类, 包含很多具体类型 Array Number Math...
	特定的对象类型 Object

对象创建

1.字面量
	var person = {name:'张三';age:'18'}
2.内置的构造函数
	var person = new Object()

对象操作 实质是对属性的增删查改

添加 obj.name = 'sz';有则覆盖没有就增加
查询 obj.name obj["name"] 遍历查询for in  通过key来拿到value
修改 同添加
删除 delete关键字 返回值是布尔值
	删除对象中不存在的属性没有任何变化,但是返回值为true

***批量创建相同结构对象

简单工厂函数(弊端,无法判断对象类型都是Object)
函数封装  参数值是各个属性,返回值是对象

自定义构造函数(也称类)
	构造函数不需要再return对象,内部使用this来初始化属性(谁调用函数,this就是谁)
	function  Person(name, age) {this.name = name;this.age = age;run = function () {}}
	1. 调用时, 必须使用 new 关键字
	2. 方法内部的this问题,哪个对象调用,this指向谁
	
自定义构造函数的属性和方法操作
	实例属性/实例方法  绑定在实例对象上面的属性和方法
	静态属性/静态方法  绑定在构造函数上面的属性和方法  
		静态属性Person.count = 0
		静态方法Person.eat = function(){}
		
属性存取器
	拦截对对象的读写操作,来执行一些其他处理,借助getter setter访问器来处理
	1.使用set get关键字   set age(val) {} get age(){}
	2.Object.defineProperty() 方法
	Object.defineProperty(对象, 属性, {
        set: function (val) {},
        get: function () {} })

对象实例方法的优化

构造函数, 绑定方法的弊端
	方法本质是对象, 对象占用内存空间
优化方案1:外部抽取一个方法,内部引用该方法
	弊端 涉及this, 外部不一定能用,违背封装特性
优化方案2:给构造函数的原型对象增加方法

原型对象
实例的原型_proto_指向构造函数的原型对象prototype,原型对象的constructor指向构造函数
1.获取原型对象的方式 构造函数.prototype;不建议使用实例对象._proto_ (非标准)
2.设置原型对象的属性/方法
	方式1:原型对象.属性 = xxx
	*方式2:替换原型对象 
		直接创建一个对象,当做是原型对象, 然后修改函数的prototype指向
		注意:替换在前,实例化在后;如果先实例化就已经指向了;需要完善:constructor指向构造函数
		使用Object.defineProperty定义来禁止遍历constructor属性
		Object.defineProperty(Admin.prototype, "constructor", {value: Admin,enumerable:false //禁止遍历});
		(方法二直接改变了原型对象,不是继承,是改变原型对象,如果要继承,推荐使用下面的方式,但也要完善constructor属性指向构造函数)
	*方式3:Mem.prototype =  Object.create(User.prototype);//创建对象时指定原型为新对象的原型对象
	*方式4:构造函数内Object.assign(User.prototype, {getName() {},getAge() {}}); // 可以多继承
	*方式5:Object.setPrototypeOf 设置对象原型(不推荐,性能消耗大,推荐方法三)
3.如果原型对象和实例对象的属性和方法,冲突? 就近原则
4. 对象类型和原型关系验证
	instanceOf : 判断一个对象, 是否是某个构造函数的原型链上
	isPrototypeOf: 判断一个对象, 是否是某个实例的原型对象
5.对象的属性存在判断
	in:判断一个对象, 是否拥有某个属性(如果对象身上没有, 会到原型对象里面查找)
	hasOwnProperty: 只到对象自身查找
	Object.keys(对象) 也只返回查找自身属性的可迭代对象

call apply bind

用来改变this指向,借用原型对象的方法
call apply立即执行,区别call是直接传参,apply是以数组方式传参 第一参数都是thisArgs
	apply在伪数组使用数组方法时很有用!
bind不是立即执行 绑定this指向, 返回一个新的方法

this指向

1.作为对象的方法来调用  this--->当前的对象
2.作为普通的函数调用    this--->window
3.作为构造函数和new使用 this--->构造函数内部新创建的对象
4.被call或者是apply调用(函数上下文调用) this--->第一个参数

继承

扩展内置对象方法
1.arr=[];arr.sum=function(){}  不推荐
2.直接给Array的原型对象添加方法   最简单,容易覆盖内置方法,要注意命名
3.创建一个Array实例,给新创建的实例的原型对象进行赋值

深拷贝和浅拷贝(指针对引用类型数据)

浅拷贝,直接赋值运算符=,拷贝的时地址值
深拷贝:
	1.手动遍历
	2.Object.assign({},要拷贝的对象1,2...)
	JSON.parse(JSON.stringify(要拷贝的对象))

链式编程

函数内部方法每个都要return this;返回本身,就可以继续调用自身的方法了

es6

1.let const

1.let和const都不支持在同一个作用域下重复定义变量
2.不存在变量提升
3.有块级作用域
4.顶层变量不会提升为window属性

2.字符串操作

新方法: startsWith() endsWith() includes() repeat()
for(... of ... )可以遍历字符串
模板字符串 `123${变量名}123` 可识别换行可使用变量

3.数值操作

ES6将全局方法parseInt()和parseFloat()放到Number对象上
Number.isInteger() Number.isFinite() 检测传入参数是否是一个有穷数
增加指数运算 2**3 = 8

4.函数操作

1.默认参数
2.多余参数   ...args 要放到最后
3.箭头函数 ()=>{} 没有自己的this内部的this就是外层代码块的this,不能使用arguments对象
注意:对象不是作用域(针对对象内的函数)

5.数组操作

1. Array.from(类数组 [, x => x*x]) callback是对参数的操作
2. find(条件函数) 找出第一个符合的数组成员并返回 callback参数 v, i, arr
	findIndex 功能同上 返回的时索引值 
3. keys(), values(), entries() 返回可迭代对象 for ... of遍历获取
4. includes() 
5. forEach()
6. map()
7. filter()
8. some()
9. every()

6.对象

1.属性简写 key名字和和value变量同样只要写一个即可
2.属性名表达式    [name] : "xxx"
3.新增方法
	Object.assign(target, source1, source2...)
	Object.keys()
	Object.values()
	Object.entries()

7.展开运算符

展开数组
展开对象

8.解构赋值

分解一个对象的结构, 从中剥离出想要的数据
1.数组的解构: [,...args] [name,age]
2.对象的解构:{...args} {data:res}
3.解构可以重命名 加:号
4.默认解构:没有解构到的数据为undefined
5.可以多层解构

9.类

之前定义类是通过构造函数来定义,es6中新增了class语法糖
    class Boy extends Person{
        constructor(name,age) {
        	super(name);
            this.age = age;
        }
        logName(){}
        // 静态属性和方法
        static money = 10000000000;
        static logMoney(){}
    }
super 通过super可以调用prototype上的属性或方法

10.新数据结构类

ES6 新增的数据结构 Set 和 Map

set不存储重复的值,本质是key和值都相同的对象
let set = new Set()
添加 set.add()  set.size  判断包含set.has()   et.delete() set.clear()
补充WeakSet 同样不存储重复的值
	弱引用:add(val) delete(val) has(val)

Map 键值对的集合
	和原生对象区别,键只能是字符串或者Symbol其他类型转换成字符串
	Map对象key可以是任意值
let map = new Map()
添加map.set(key,value) map.get(key)  delete map[key] map.delete(key)  map.foreach((key)=>{})

set和map不能使用下标得到值

Symbol
独一无二,常用于枚举值区分
let LEVEL = {
    great: Symbol(), 
    good: Symbol(), 
    bad: Symbol()
}

11.迭代器&生成器

产生:遍历的多层嵌套问题,很多时候, 只想使用数组中的元素, 并不想使用索引
解决方法:使用for...of遍历

迭代器:迭代器是专用于迭代的对象
	所有迭代器对象拥有next()方法,返回{value:值,done:Boolean}
可迭代对象
	Array/Set/Map/String是可迭代对象
	Obj对象不是可迭代对象,要借助keys/values/entries,例如:Object.keys(obj)
	可迭代对象具有Symbol.iterator属性
	for-of 循环专注于对结合内容的操作,每次循环调用迭代器next()方法, 直到返回的结果中done为true
生成器(又叫星星函数)
	function *generator() { yield 表达式 }
	碰到每一个yield, 就会临时挂起函数执行, 返回结果, 等待下一次next()调用
	next(val)可以传值
	return 提早结束生成器, 可向外界传递结果
	生成器委托  第三个生成器是前面两个的组合 对第三个生成器next(),相当于委托内部的生成器们来做事

JS编码经验

  1. 代码可读性

    1.命名
    见名知意
    变量名/函数名 小驼峰命名
    常量 纯大写 多个单词,使用_分割
    全局变量 纯大写 多个单词,使用_分割 为了区分常量以G_ 开头
    类名 大驼峰命名
    2.空格
    运算符周围加空格
    数组元素分割符, 后面加空格
    对象key: 后面加空格
    分支循环,代码块 { }, 左花括号前加空格
    3.缩进
    内部代码块缩进

  2. 代码的健壮性

    1. 变量声明时, 尽可能初始化数据 避免因为undefined 产生的错误
    2. 使用 === 比较
    3. 容错处理
      1. 参数类型,js 是动态类型,在使用之前,尽量做一个判定
      2. 参数默认值 if (a === undefined) a = 0;
      3. 根据不同业务逻辑需求做数据有效性检查
    4. 异常处理
      1)抛出异常 throw 字符串或对象
      2)捕获异常 try{}catch (e){}finally{}
  3. 性能提优+内存优化

    1. 避免滥用全局变量 避免生命周期过长;局部变量访问快于全局
    2. 变量使用前,一定要声明
    3. 变量声明放在作用域顶部
    4. 不要定义数值、字符串或布尔对象 ----new Stirng(“it”)
    5. 勿使用 new Object() 可以使用{}
    6. 减少循环中的处理 for(var i = 0, len = arr.length; i < len; i++) { }
    7. 避免不必要的变量
    8. 延迟 JavaScript 加载
    9. 插入迭代值 var a=arr[i]; i++;----var a=arr[i++]
    10. 重复使用的调用结果,事先保存到局部变量
    11. 函数中减少全局变量的使用
    12. 减少DOM操作 DOM操作时脚本中最耗资源的操作
    13. 闭包产生的内存泄露
    14. 资源合并与压缩
      1. 将外部的脚本或样式进行压缩
      2. 将外部的多个脚本或样式进行合并
      3. 资源压缩 例如图片压缩/精灵图/懒加载

Web API

https://developer.mozilla.org/zh-CN/docs/Web/API

BOM

window

  • 浏览器的顶级对象,代表是整个浏览器的窗口, 同时也是网页中的全局对象

    常用方法
    对话框 alert() prompt() confirm()
    页面加载事件 onload onunload
    打开关闭窗口 window.open(“url”) close()
    定时器 setTimeout(()=>{},delay) clearTimeout(timer)
    setInterval(()=>{},delay) clearInterval(timer)

    本地存储(只能存储字符串类型数据)
    localStorage 永久生效,除非手动删除,方法和下面的相同
    sessionStorage 生命周期为关闭浏览器窗口,同一个窗口(页面)共享
    sessionStorage.setItem(key,value) .getItem(key) .remove(key) .clear()清除所有

navigator

  • 代表的当前浏览器的信息,通过该对象可以来识别不同的浏览器

    识别不同的浏览器
    使用userAgent来判断浏览器的信息,userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,不同的浏览器会有不同的userAgent
    var userAgent = navigator.userAgent;
    if(/firefox/i.test(userAgent)){
    alert(“我是火狐”);
    }else if(/chrome/i.test(userAgent)){
    alert(“我是谷歌”);
    }else if(/msie/i.test(userAgent)){
    alert(“我是IE”);
    }else if(“ActiveXObject” in window){
    alert(“我是IE11”);
    }

location

  • 代表当前地址栏信息,通过Location获取地址栏信息,或者操作浏览器跳转页面

    url跳转 location=“网址” location.assign(“网址”)
    刷新 location.reload() 加true参数强制清空缓存并刷新
    跳转 location.replace(“网址”) 新的页面替换当前页面,没有历史记录,不能后退

history

  • 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录

  • 因为隐私问题,不能获取具体的历史记录,只能操作向前向后

    length 获取当前访问的链接数量
    back() 后退一步
    forward() 前进一步
    go() 1 2 -1 -2 相应的跳转几个页面

screen

  • 屏幕对象,获取屏幕信息

    width 显示屏幕宽度
    availHeight 显示屏幕高度 任务栏除外
    availWidth 显示屏幕宽度 任务栏除外

DOM

  • 文档对象模型

  • 常用操作:元素获取,元素操作(事件/属性),创建元素,删除元素

    Document对象
    Document对象 Window对象一部分,window.document属性对其进行访问
    常用属性:
    head
    title
    body
    childNodes 所有的子节点
    children 所有元素节点

元素获取

1.id获取元素
document.getElementById('box'); 返回一个dom对象
2.标签名获取元素
document.getElementsByTagName('div'); 返回一个伪数组
3.name获取元素
document.getElementsByName('like'); 返回一个伪数组
4.类名获取元素
document.getElementsByClassName('box');返回一个伪数组
5.选择器获取元素
document.querySelector('#box');
6.元素关系获取元素
	也可以根据children来获取元素节点
	1)获取父节点
	parentNode节点,parentElement元素节点
	2)上一个兄弟节点
	previousSibling,previousElementSibling
	3)下一个兄弟节点
	nextSibling,nextElementSibling
	4)获取标签中第一个子节点
	firstChild,firstElementChild
	5)获取标签中最后一个子节点
	lastChild,lastEelementChild
	6)获取任意兄弟节点
	obj.parentNode.children[1]

事件

事件三要素
事件源:触发事件元素 事件名称 事件处理程序

使用方式:
1.在标签中绑定事件和对应的执行代码,耦合不方便维护,不推荐使用
2.获取元素,js来绑定
绑定方式1: el.onclick = function(){} ,通用,但是多次绑定会覆盖
	el.onclick = null
绑定方式2: el.box.addEventListener('click', eventCode, false);可以绑定多次, 正序执行
	box.removeEventListener('click', eventCode, false);
绑定方式3:	box.attachEvent('onclick', eventCode); ie678倒序执行
	box.detachEvent('onclick', eventCode);
借助惰性函数进行优化
function addEventListener(element, type, fn) {
  if (element.addEventListener) {
    element.addEventListener(type, fn, false);
  } else if (element.attachEvent){
    element.attachEvent('on' + type,fn);
  } else {
    element['on'+type] = fn;
  }
}

事件冒泡和事件委托
阻止冒泡:event.stopPropagation();
事件委托:借助事件冒泡机制, 直接监听他们的父元素的事件
	在处理函数中, 判定事件来源 event.target
事件捕获:模式修改 useCapture

常用事件
鼠标: onclick ondblclick onmousedown onmouseup onmouseover onmouseout	onmousemove
	mouseenter和mouseover区别:mouseover经过子盒子还会触发 mouseenter只有经过自身盒子才会触发
	mouseenter搭配鼠标离开mouseleave 同样不会冒泡
键盘:onkeydown onkeyup onkeypress
加载: onload某个页面或图像被完成加载 onunload用户退出页面
表单: onfocus元素获得焦点 onblur元素失去焦点 onchange 用户改变域的内容 onreset重置按钮被点击 onsubmit提交按钮被点击
onresize窗口或框架被调整尺寸 onscroll 页面滚动

事件对象Event
键盘事件:key: "R" ;keyCode: 82
鼠标事件:button 012 左中右键
	screenX/Y 相对于屏幕的鼠标点击坐标
	clientX/Y 相对于浏览器的鼠标点击坐标
	pageX/Y 相对于页面的鼠标坐标
	offsetX/Y 相对于元素的鼠标坐标
window的事件
	pageshow事件重新加载页面(清除缓存的重新加载)
	onload事件
	resize事件
document事件	
	DomContentLoaded页面加载完成


preventDefault()阻止默认行为
stopPropagation()阻止事件冒泡

属性操作

方式1:元素.属性名  无法获取自定义属性
方式2:getAttribute(名称);setAttribute(名称,值)removeAttribute(名称)  可以获取自定义属性

常用属性:
非表单元素的属性 href、title、id、src、className
表单元素属性 value type disabled checked selected
样式操作:
style方式设置的样式显示在标签行内,宽高设置是字符串要+px

节点创建和删除

创建节点
document.write('可以写标签')
e.innerHTML = '可以写标签'
document.createElement('标签名') 返回dom对象

appendChild('对象名')
insertBefore('对象名')
removeChild('对象名')
replaceChild('对象名')

克隆节点
新节点=要复制的节点.cloneNode(参数) // 参数deep: 是否递归复制子孙节点

删除节点
var btn = document.getElementById("btn"); btn.remove();
word.parentNode.removeChild(word); // 自杀

三大家族

offset(用于获取元素位置offsetLeft offsetTop)

  • 用于获取元素自身的一些参数

    .offsetParent 得到距离自己最近的带有定位的父级元素
    offsetWidth offsetHeight 自身宽高 内容+边框+内边距
    offsetLeft offsetTop 子盒子边框到定位父盒子边框的距离

    offsetXXX 和 style.XXX的区别
    style获取行内样式设置的数据,可以用来设置;offset获取最终位置数据(只读)
    style.left 以margin 左上角为准;offsetLeft 以border 左上角为准

scroll(获取滚动距离scrollTop window.pageYOffset)

网页正文全文宽: document.body.scrollWidth
网页正文全文高: document.body.scrollHeight
网页被卷去的高: document.body.scrollTop  ***高频使用  可读写
网页被卷去的左: document.body.scrollLeft   可读写
scrollWidth 包含隐藏的子元素的宽度
scrollHeight 包含隐藏的子元素的高度

兼容写法 *****
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0; 
var scrollLeft = window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0;

window.scrollTo(x,y) 把内容滚动到指定的坐标
window.scrollBy(x,y)  滚动到相对位置
参数:左上角显示的文档的 x 坐标 左上角显示的文档的 y 坐标

client(获取元素大小 clientWidth clientHeight)

clientWidth 边框内部的宽度(padding+内容区) 不含边框
clientHeight 边框内部的高度(padding+内容区) 不含边框
clientLeft 左边边框的宽度+滚动条宽度  不用
clientTop 上面的边框的宽度+滚动条宽度 不用

js函数防抖

  • 短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行
    // 非立即执行版
    function debounce(func, wait) {
        let timer;
        return function() {
          let context = this; // 注意 this 指向
          let args = arguments; // arguments中存着e
             
          if (timer) clearTimeout(timer);
     
          timer = setTimeout(() => {
            func.apply(context, args)
          }, wait)
        }
    }
    // 立即执行版
    function debounce(func, wait) {
        let timer;
        return function() {
          let context = this; // 这边的 this 指向谁?
          let args = arguments; // arguments中存着e
     
          if (timer) clearTimeout(timer);
     
          let callNow = !timer;
     
          timer = setTimeout(() => {
            timer = null;
          }, wait)
     
          if (callNow) func.apply(context, args);
        }
    }
    
    // 合成版
    /**
       * @desc 函数防抖
       * @param func 目标函数
       * @param wait 延迟执行毫秒数
       * @param immediate true - 立即执行, false - 延迟执行
       */
    function debounce(func, wait, immediate) {
        let timer;
        return function() {
          let context = this,
              args = arguments;    
              
          if (timer) clearTimeout(timer);
          if (immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
              timer = null;
            }, wait);
            if (callNow) func.apply(context, args);
          } else {
            timer  = setTimeout(() => {
              func.apply(context, args);
            }, wait)
          }
        }
    }

js函数节流

  • 连续触发事件但是在 n 秒中只执行一次函数。即 2n 秒内执行 2 次… 。节流字面意思,稀释函数的执行频率

   // 时间戳版
   function throttle(func, wait) {
       let previous = 0;
       return function() {
         let now = Date.now(); // 获取现在的时间
         let context = this;
         let args = arguments;
         if (now - previous > wait) { // 判断现在时间-之前时间是否大于设定的wait值
           func.apply(context, args); // 执行函数
           previous = now; // 给之前时间赋值为现在时间
         }
       }
   }
   // 定时器版1
   function throttle(func, wait) {
       let timeout;
       return function() {
         let context = this;
         let args = arguments;
         if (!timeout) {  // 没有定时器
           timeout = setTimeout(() => { // 设置定时器
             timeout = null;  // 清空定时器
             func.apply(context, args)  // 执行函数
           }, wait)
         }
       }
   }
   // 定时器版2
   function throttle(fn,delay){
       let valid = true  // 设置标记  false为节流中  
       return function() {
          if(!valid){
              return false
          }
         let context = this;
         let args = arguments;
           valid = false
           setTimeout(() => {
               fn.apply(context,args)
               valid = true;
           }, delay)
       }
   }
   /**
    * @desc 函数节流
    * @param func 函数
    * @param wait 延迟执行毫秒数
    * @param type 1 表时间戳版,2 表定时器版
    */
   function throttle(func, wait, type) {
     if (type === 1) {
       let previous = 0;
     } else if (type === 2) {
       let timeout;
     }
     return function() {
       let context = this;
       let args = arguments;
       if (type === 1) {
           let now = Date.now();
    
           if (now - previous > wait) {
             func.apply(context, args);
             previous = now;
           }
       } else if (type === 2) {
         if (!timeout) {
           timeout = setTimeout(() => {
             timeout = null;
             func.apply(context, args)
           }, wait)
         }
       }
     }
   }



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值