Nombase公司 | 1992 | 开发出第一门客户端脚本语言,专门用于表单校验,命名为C–,后来更名为ScriptEase |
---|---|---|
Netscape(网景)公司 | 1995 | 客户端脚本语言:LiveScript,请来SUN公司专家,修改LiveScript为JavaScript |
微软 | 1996 | 抄袭JavaScript开发JScript语言 |
ECMA(欧洲计算机制造商协会) | 1997 | 统一了三家的,ECMAScript,就是所有客户端脚本语言标准。JavaScript=ECMAScript+JavaScript自己特有的东西(BOM+DOM) |
BOM管的:
A区(浏览器的标签页,地址栏,搜索栏,书签栏,窗口放大还原关闭按钮,菜单栏等等)
B区(浏览器的右键菜单)
C区(document加载时的状态栏,显示http状态码等)
D区(滚动条scroll bar)
DOM管的:E区
第一章:BOM
1.1、概念
BOM:浏览器对象模型,与浏览器交互的方法和接口,通过JS *** 作浏览器window / navigator / history / screen
1.2、组成:window、Navigator、Screen、 History、Location① window:窗口对象,window也是网页中的全局对象
window对象不需要创建,可以直接使用window使用。window.方法名();
②History:历史记录对象
//创建(获取)
window.history
//方法
back(): 加载history列表中的前一个URL
forward():加载history列表中的下一个URL
go(参数): 加载history列表中某个具体页面
正数:前进几个历史记录 go(1)=forward()
负数:后退几个历史记录 go(-1)=back()
//属性
length:返回的是当前窗口历史列表中的 URL数量。
③Location:地址栏对象
//创建(获取)
window.location
//方法
reload():重新加载当前文档,刷新
//属性
href 设置或返回完整的URL
var href = location.href;
④ Navigator:浏览器对象,包含大量有关Web浏览器的信息,在检测浏览器及 *** 作系统上非常有用
window.navigator.appCodeName //浏览器代码名
window.navigator.appName //浏览器步伐名
window.navigator.appMinorVersion //浏览器补钉版本
window.navigator.cpuClass //cpu类型 x86
window.navigator.platform // *** 作体系类型 win32
window.navigator.plugins
window.navigator.opsProfile
window.navigator.userProfile
window.navigator.systemLanguage //客户体系语言 zh-cn简体中文
window.navigator.userLanguage //用户语言,同上
window.navigator.appVersion //浏览器版本(包括 体系版本)
window.navigator.userAgent//用户代理头的字符串表示
window.navigator.onLine //用户否在线
window.navigator.cookieEnabled //浏览器是否撑持cookie
window.navigator.mimeTypes
⑤Screen:用于获取某些关于用户屏幕的信息,也可用window.screen引用它
window.screen.width //屏幕宽度
window.screen.height //屏幕高度
window.screen.colorDepth //屏幕颜色深度
window.screen.availWidth //可用宽度(除去任务栏的高度)
window.screen.availHeight //可用高度(除去任务栏的高度)
1.3、方法
①d出框相关
alert():显示带有一段消息和一个确认按钮的警告框
confirm():显示带有一段消息以及确认按钮和取消按钮的对话框
prompt():可以d出一个提示框,显示可提示用户输入的对话框//提示用户输入信息,接受两个参数,即要显示给用户的文本和文本框中的默认值,将文本框中的
②打开关闭
close():关闭浏览器窗口
open():打开一个新的浏览器窗口
③定时器
setTimeout():在指定的毫秒数后调用函数或计算表达式,返回值:唯一标识,用来取消定时器
clearTimeout():取消setTimeout()方法设置的timtout
setInterval():按照指定的周期(以毫秒计)来调用函数或计算表达式
clearInterval():取消由setInterval()设置的timeout
注:
如果文档包含框架(frame 或 iframe 标签),浏览器会为 HTML 文档创建一个 window 对象,并为每个框架创建一个额外的 window 对象。
② window.frames 返回窗口中所有命名的框架
③parent是父窗口(如果窗口是顶级窗口,那么parentselftop)
top是最顶级父窗口(有的窗口中套了好几层frameset或者iframe)
self是当前窗口(等价window)
opener是用open方法打开当前窗口的那个窗口
第二章:DOM 2.1、概念文档对象模型,document object model,通过dom就可以随意更改web页面元素
2.2、核心DOM模型针对任何结构化文档的标准模型
XML DOM:针对XML文档的标准模型
HTML DOM:针对HTML文档的标准模型
1)、 Document:文档对象
**2)、**Element:元素对象
getElementById():根据id属性值获取元素对象,id属性值一般唯一
getElementsByTagName():根据元素返回值是数组
getElementsByClassName():根据class属性值获取元素对象,返回值是数组
getElementByName():根据name属性值获取元素对象,返回值是一个数组
3)、创建DOM对象
createAttribute(name):
createComment():
createElement():
createTextName():
4)Text:文本对象
5)Comment:注释对象
6) Node:节点对象,其它5个的父对象
2.3、属性1)Element:元素对象
获取 创建:通过document来获取和创建
removeAttribute():删除属性 setAttribute():设置属性
var element_a = document.getElementsByTagName("a")[0];
element_a.setAttribute("href","http://www.baidu.com");
2) Node:节点对象,其它五个的父对象
特点:所有DOM对象都可以被认为是一个节点
分类:文档节点、元素节点、 属性节点、文本节点
appenchild():向节点的子节点列表的结尾添加新的子节点;
insertBefore()
removechild():删除(并返回)当前节点的指定子节点
replacechild():用新节点替换一个子节点
parentNode:返回节点的父节点
2.4、DOM事件模型(先捕获后冒泡)
DOM事件流:事件发生时交互在元素节点间按特定顺序传播,这个传播过程是DOM事件流,在页面中接收事件的顺序
分为三个阶段:捕获阶段->当前目标阶段->冒泡阶段
1)冒泡型事件模型(IE事件流): button->div->body 1-2-3,IE9+冒泡到window
2)捕获型事件模型(Netscape事件流): body->div->button 3-2-1
var father = document.querySelector('.father');
var son = document.querySelector('.son');
document.addEventListener('click',()=>{
alert('document');
},false);
father.addEventListener('click',()=>{
alert('father');
},false);
son.addEventListener('click',()=>{
alert('son');
},false); false:冒泡阶段;true:捕获阶段
注意:
1.Js代码中只能执行捕获或者冒泡其中的一个阶段
2.Onlick 和attachEvent 只能得到冒泡阶段
3.addEventlistener(type,listenert,usecapture)第三个参数如果是true,表示事件
捕获阶段调用事件处理程序;如果是false(默认),表示事件冒泡阶段调用事件处理程序。
4.实际开发中很少使用事件捕获,事件冒泡更值得关注
5.有些事件是没有冒泡的,比如onblur、onfocus、onmouseenter、onmouseleave
6.事件冒泡有时会带来麻烦,有时会很巧妙的做某些事件
取消事件冒泡和捕获
bubbles || stopPropagation || stopImnediatepropagation || cancleBubble;
2.5、事件委托/事件代理子集的事件委托给父集处理
<ul>
<li >1</li>
<li >2</li>
<li >3</li>
</ul>
let ul = document.querySelector('ul')
ul.onclick = function (e) {
ul.removeChild(e.target) //只给ul绑定删除事件,li可以用到父集的方法
}
2.6、事件监听机制
1)、概念:某些组件被执行了某些 *** 作后,触发某些代码的执行。
事件:某些 *** 作,如单击、双击、键盘按下、鼠标移动
事件源:组件,如:按钮、文本输入框。。。
注册监听:将事件、事件源、监听器结合在一起,当事件源上发生了某件事,则触发执行某个监听器代码。
2)、事件类型 Event
onclick 单击事件 doubleclick 双击事件 //点击事件
onblur 失去焦点 onfocus 元素获得焦点 //焦点事件
onload:一张页面或一副图像完成加载 //加载事件
onmousedown鼠标按钮被按下 //鼠标事件
onmouseup鼠标按钮被松开
onmousemove 鼠标被移动
onmouseout 鼠标从某元素移开
onmouseover鼠标移到某元素之上
onkeydown 某个键盘按钮被按下 //键盘事件
onkeyup 某个键盘按钮被松开
onkeypress 某个键盘按钮被按下或松开
onchange 域的内容被改变 //选中和改变
onselect 文本被选中
onsubmit 确认按钮被点击 //表单事件
onreset 重置按钮被点击
第三章:JS
1、数据类型
①基本数据类型:number / boolean / string / null / undefined / Symbol(ES6) / BigInt(ES10)
②引用类型:object(包含Function、Date、Math、Array、RegExp)
③在JS中提供3种包装类,可以将基本数据类型转换为对象,String()、 Number()、 Boolean()
注:
基本类型:保存的是数值,直接存储在栈中
基本数据经常被频繁使用,存在栈中,占用空间小,大小固定
引用类型:保存的是地址值,存储在堆中,在栈中保存数据的引用地址,这个引用地址指向的是对应的数据,以便快速查找到堆内存中的对象。
引用类型同时存在栈和堆中,占用空间大,大小不固定,在栈中存储指针指向堆中实体的起始
栈内存是自动分配内存的。而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象的时候都要把它设置为null,从而减少无用内存的消耗
地址,解释器寻找引用值时,先在栈中找地址,获得地址后从堆中获得实体
var number = new Number(3); //object
var boolean = new Boolean(true);
var string = new String("ok");
number.b = 34 //Number(3,b:34)
js的数据存储是使用二进制,如果二进制前三位都是0,是object类型,null的二进制全是0,(type null 是object)
000:对象
1:整型
010:双精度类型
100:字符串
110:布尔类型
2、判断数据类型 有四种
1)typeof:判断基本数据类型返回对应的类型;判断引用类型,一律返回object,不能区分null/undefined
2)instanceof:判断实例是否属于某种类型,A instanceof B(A是B实例,返回True,不然false)
缺点:只能判断对象是否存在于目标对象的原型链上
原理:查找目标对象的原型链
var a = []
a instanceof Array //true
3)constructor
缺点:不能判断null和undefined;
当一个函数F被定义时,JS引擎会为F添加prototype原型,然后再在prototype上添加一个constructor属性,并让其指向F的引用
var b = []
console.log(b.constructor,b.constructor === Array) //true
var fn = new F()
console.log(F.prototype, fn.constructor == F)
4)Object.prototype.toString.call():(这个是判断类型最准的方法)
toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,更严格的讲,是 toString运行时this指向的对象类型, 返回的类型格式为[object,xxx],(String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,… )基本上所有对象的类型都可以通过这个方法获取到。
var c = []
Object.prototype.toString.call(c) //[object Array]
注:
a、所有原型链都指向Object,必须通过Object.prototype.toString.call获取
b、instanceof与constructor判断数组对象的弊端----不能判断iframe
var iframe = document.createElement('iframe')
document.body.append(iframe)
var xArray = window.frames[window.frames.length - 1].Array
var arr = new xArray(1,2,3)
console.log(arr instanceof Array) //true
console.log(arr.constructor === Array) //true
3、数据类型转换
1)、转数字:Number()方法,parseInt(),parseFloat()
Number()
Number('true') //NaN
Number('3') //3
parseInt()
parseInt('23hv') //23
parseFloat()
parseFloat()把字符串转换成浮点数,parseFloat()和parseInt非常相似,不同之处在与parseFloat会解析第一个. 遇到第二个.或者非数字结束如果解析的内容里只有整数,解析成整数。
隐式转换:
var str="123";
var num=str-0; //Number
2)、转布尔值:Boolean()方法
0、空字符串、null、undefined、NaN 都转成false,其他都是true
隐式转换
var vvv = 'dfd'
var bool = !!vvv;
console.log(bool,typeof bool) //true 'boolean'
3)、转字符串:toString(),String()、隐式
toString():不可以转null和underfined
var a = true
a.toString() //'true',String类型
String():都可以转
console.log(String(null));
隐式转换:'+'两边一个是字符串类型,一个是其他类型,会先把其他类型转换为字符串,在拼接,最后是字符串类型
var a = true;var str = a+ ''
console.log(str) //'true'
4、null和undefined区别
相同点:用if判断,两个值都转为false
不同点:使用number()方法判断,number(null)为0 number(undefined)为NaN
null是定义后赋值为null
undefined是定义后未赋值
var a a->undefined typeof a -> ‘undefined’
null的用处:
①赋值为null,是为了给赋值为空对象 var a = null
②让不被引用的赋值为null,将被垃圾回收机制回收
注:判断一个数据是不是NaN
首先,它不是数字,typeof(NaN)–>number
利用NaN的定义,用typeof判断是否为number类型并且判断是否满足isNaN
利用NaN是唯一一个不等于任何自身的特点 n!==n
5、var let const区别var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
const定义的变量不可以修改,而且必须初始化。
let是块级作用域,函数内部使用let定义后,对函数外部无影响。
Var声明的变量会挂载在window上,而let和const声明的变量不会
Var声明的变量存在变量提升,let和const不存在变量提升
同一作用域下var可以声明同名变量,let和const不可以
Let和const声明会形成块级作用域
Let暂存死区
const定义的是常量,不能修改,但是如果定义的是对象,可以修改对象内部的数据
6、箭头函数与普通函数区别箭头函数是匿名函数,不能被作为构造函数,不能被new
箭头函数不绑定aruguments,用rest参数解决
箭头函数不绑定this,会捕获上下文的this,作为自己的this
箭头函数通过call() apply()调用函数,只传入一个参数,对this没有影响
箭头函数没有原型属性
7、this指向问题以函数调用,this就指向windows
以方法的形式调用,this就是调用方法的那个对象
以构造函数的形式调用时,this是新创建的那个对象
使用call和apply调用时,this指向的那个对象
this的值是浏览器传过来的,指向很多,谁调用就指向谁
2)改变this指向的函数:call、apply、bind
①call和apply实现思路主要是:
判断是否是函数调用,若非函数调用抛异常
通过新对象(context)来调用函数:给context创建一个fn设置为需要调用的函数;结束调用完之后删除fn
call
Function.prototype.myCall = function (context) {
if (typeof this !== 'function') { // 先判断调用myCall是不是一个函数,这里的this就是调用myCall的
throw new TypeError("Not a Function")
}
context = context || window
// 不传参数默认为window
context.fn = this
// 保存this
let args = Array.from(arguments).slice(1) //Array.from 把伪数组对象转为数组
let result = context.fn(...args) // 调用函数
delete context.fn
return result
}
apply
Function.prototype.myApply = function (context) {
if (typeof this !== "function") { // 判断this是不是函数
throw new TypeError("Not a Function")
}
let result
context = context || window
// 默认是window
context.fn = this
// 保存this
if (arguments[1]) { // 是否传参
result = context.fn(...arguments[1])
} else {
result = context.fn()
}
delete context.fn
return result
}
②bind实现思路
判断是否是函数调用,若非函数调用抛异常
返回函数:判断函数的调用方式,是否是被new出来的,new出来的话返回空对象,但是实例的__proto__指向_this的prototype
完成函数柯里化 Array.prototype.slice.call()
Function.prototype.myBind = function(context){
if(typeof this !== "function") { // 判断是否是一个函数
throw new TypeError("Not a Function")
}
const _this = this // 保存调用bind的函数
const args = Array.prototype.slice.call(arguments,1) // 保存参数
return function F () { // 返回一个函数
if(this instanceof F) { // 判断是不是new出来的
,如果是new出来的,返回一个空对象,
return new _this(...args,...arguments) // 创建出来的实例的__proto__指向_this的prototype,且完成函数柯里化
}else{ // 如果不是new出来的改变this指向,且完成函数柯里化
return _this.apply(context,args.concat(...arguments))
}
}
}
8、arguments
调用函数时,浏览器每次都会传入两个隐含的参数,this,arguments
arguments是一个类数组对象,可以通过索引 *** 作数组,也可以获取长度
在调用函数时,传递的实参都会封装到arguments中
function fun() {
console.log(arguments instanceof Array ) // false
console.log(arguments.length) //长度就看传了几个参数
console.log(arguments[0]) //arguments[0]可以索引到实参的值
console.log(arguments.callee) //找到对应的函数对象
console.log(arguments.callee === fun)
}
fun("hello","ok")
9、闭包是什么,有什么特性,对页面有哪些影响
父函数中返回的子函数,一个函数和它周围状态的引用捆绑在一起的组合
闭包是指有权访问另一个函数作用域中的变量的函数
优点: 延长外部函数局部变量的生命周期;避免全局变量污染
缺点:变量不会销毁,容易造成内存泄露
注意: 合理的使用闭包,用完闭包要及时清除(销毁)
var str = 'wl'
var obj ={
str:'eeee',
getData:function(){
console.log('第1个函数',this) //this指向object,包含
return function(){
console.log('第二个函数',this) //this指向window
return this.str
}
}
}
console.log(obj.getData()()) //wl
console.log(obj.getData()) //ƒ (){ return this.str}
console.log(obj.getData) //ƒ (){return function(){return this.str}}
闭包的应用
设计模式中的单例模式for循环中的保留i的 *** 作防抖和节流函数柯里化 10、深拷贝,浅拷贝数值类型在栈内存存储,会实现深拷贝
引用类型在栈、堆存储,栈存储的是指向堆的地址,浅拷贝导致obj1和obj2指向同一个地址,得用具体的方法才能实现深拷贝,方法各有优缺点
第一种、JSON.parse(JSON.stringify())
问题:函数无法拷贝; 正则无法拷贝;undefined 无法拷贝
优点: 二级以下也可以实现深拷贝
let obj1 = {
a:1,
say(){
console.log('1')
},
reg:/\d/,
data:undefined,
person:{
name:"wl"
}
}
let obj2 = JSON.parse(JSON.stringify(obj1));
obj1.person.name = "lxy"; //拷贝之后修改
console.log(obj2)
第二种、object.assign()
优点;可以拷贝函数;可以拷贝正则 ;可以拷贝undefined
问题:二级以下无法实现深拷贝
let obj2 = {}
Object.assign(obj2,obj1)
第三种、递归
优点:可以拷贝函数;可以拷贝正则 ;可以拷贝undefined,二级以下可拷贝
var obj= { "name":"豪豪", "age":22, "job":"程序员", "height":175,
"type":{"character":"tender"}}
obj.__proto__.say=function(){ };
function deepCopy(obj){
var copyObj={ };
for(var key in obj){
if(obj.hasOwnProperty(key) == true){
if(obj[key] instanceof Object){
copyObj[key] = deepCopy(obj[key])
}else{
copyObj[key] = obj[key]
}
}
}
return copyObj;
}
var obj2 = deepCopy(obj)
console.log(obj2)
11、js常见的内存泄漏
程序中己动态分配的堆内存由于某种原因程序未释放或无法释放引发的各种问题
js中可能出现的内存泄漏情况:结果:变慢,崩溃,延迟大等
原因:
意外的全局变量
dom 清空时,还存在引用
定时器未清除
子元素存在引起的内存泄露
闭包
12 、js垃圾回收方式
1)怎么确定是垃圾:当一个对象没有任何的变量引用指向它的时候,再也无法 *** 作它,这种对象在堆内存中存储过多时,会导致内存卡顿,就需要被清理
2)回收目的:防止内存泄漏(已经不需要的某一块内存还一直存在着),垃圾回收机制就是不停歇的寻找这些不再使用的变量,并且释放掉它所指向的内存。
3)怎么清除:JS垃圾回收机制自己回收
①标记清除:大部分浏览器使用这种垃圾回收,当变量进入执行环境(声明变量)的时候,垃圾回收器将该变量进行了标记,当该变量离开环境的时候,将其再度标记,随之进行删除。
②引用计数:这种方式常常会引起内存的泄露,主要存在于低版本的浏览器。它的机制就是跟踪某一个值得引用次数,当声明一个变量并且将一个引用类型赋值给变量得时候引
13、防抖节流一个函数执行一次后,只有大于设定的执行周期才能执行第二次
在规定时间内,只让函数触发的第一次生效,后面不生效
防抖:设置setTimeout,在一定时间间隔内,多次触发变成一次触发
function debounce(fn,delay) {
var timer = null;
return function () {
//清除上一次的延迟器
clearTimeout(timer)
//重新设置新的延时器
timer = setTimeout(function () {
fn.apply(this)
},delay);
}
}
document.getElementById('btn').onclick = debounce(function () {
console.log("当前事件被触发流"+Date.now())
},1000)
节流:减少一段时间的触发频率
function throttle(fn,delay) {
var lasttime =0;
return function () {
var nowTime = Date.now();
if(nowTime-lasttime > delay){
fn.call(this);
lasttime = nowTime;
}
}
}
document.onscroll = throttle(function () {
console.log('throttle函数被触发流'+Date.now())
},200);
14、作用域与作用域链
规定变量和函数的可使用范围称作作用域,分两种,全局作用域和函数作用域
全局作用域
打开页面时,全局作用域创建,关闭页面时全局作用域销毁
创建的变量,是windows的属性
创建的函数,是windows的方法
变量要提前声明,再使用。function函数声明和var会提前被浏览器解析到,所以,调用的位置在创建函数前和后都能找到对应的定义。
函数作用域
调用函数时,函数作用域创建,调用结束,函数作用域销毁
函数作用域可以访问到全局作用域 ;全局作用域访问不到函数作用域
在函数作用域中 *** 作一个变量,会在自己作用域范围找,没有,就去上一层找
作用域链:每个函数都有一个作用域链,查找变量或者函数时,需要从局部作用域到全局作用域依次查找,这些作用域的集合称作作用域链。
15、原型、原型链所有的函数都有prototype属性(原型),显示原型,定义函数时自动添加
所有的对象都有__proto__属性,隐式原型,创建对象时自动添加
显示原型与隐示原型
student.__proto__ === Student.prototype //true
隐式原型 显示原型
在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个proto属性指向这个原型,而函数的原型是一个对象,所以这个对象也会有一个proto指向自己的原型,这样逐层深入直到Object对象的原型,这样就形成了原型链。
16、javaScript页面跳转,页面重定向window.location.replace("url")
window.location.href="url"
17、ajax如何使用
用来实现异步请求,好处是在不加载整个页面的情况下实现局部网页加载
一个完整的请求包含5个步骤
最实用的异步请求是axios
var xhr = new XMLHttpRequest()
xhr.open('get', 'http://127.0.0.1:3000/ajax')
xhr.send()
xhr.onload = function() {
console.log(xhr.responseText)
}
18、Date
1、创建:
var date = new Date();
2、方法:
tolocaleString():返回当前data对象对应的时间本地字符串格式
getTime();获取毫秒值。返回当前时期对象描述的时间到1970.1.1零点的毫秒值
19、Math
1、创建
*特点:Math对象不用创建,直接使用。 Math.方法名();
2、方法
random():返回0-1之间的随机数;[0.0-1.0)
ceil(x):对数进行下舍入
floor(x):对数进行上舍入
round(x):把数四舍五入为最接近的整数
3、属性 PI
parseInt(125.8)->125直接砍掉小数
20、string
trim()
repeat()
match()
indexOf()返回字符串索引指定字符第一次出现的位置
lastIndexOf()返回字符串索引指定字符最后一次出现的位置
includes() 字符串中有没有包含指定字符,有返回true无返回false 区分大小写
21、Array数组方法
返回新数组的方法:filter 、concat、 slice
添加数据:array[0] = 1;
array.push(2,3,4)
array.length 数组长度
array[array.length] = 678 //这个方法总给数组最后一个赋值
arr.push()/arr.pop() 末尾推入和d出,改变原数组, 返回是推入/d出值的元素
arr.unshift()/arr.shift():头部推入和d出,改变原数组,返回 *** 作项,只能 *** 作一个数
arr.concat() 连接两个数组 返回值为连接后的新数组,不影响原数组, 浅拷贝
arr.sort()/arr.reverse() 排序/反转,改变原数组,返回 *** 作项,
str.split() 将字符串转化为数组
slice(start, end) : 返回截断后的新数组,不改变原数组
splice(start,number,value…): 返回删除元素组成的数组,value 为插入项,改变原数组,将原数组从索引往后数n个删除并返回切出来的
arr.forEach(callback) 遍历数组,无return 即使有return,也不会返回任何值,
arr.map(callback) 映射数组(遍历数组),有return 返回一个新数组 。
arr.filter(callback) 过滤数组,返回一个满足要求的数组
var arr = [2,4,6,23,12,4];
var newArr = arr.filter(item => item>20)
arr.indexOf(value, fromIndex)/arr.lastIndexOf(value, fromIndex) // 查找数组项,返回对应的下标
reduce / reduceRight(fn(prev,cur),defaultPrev) //两两执行,prev 为上次化简函数的return 值,cur 为当前值(从第二项开始)
arr.includes(item) //includes判断数组有没有item,有返回true,没有返回false
数组去重练习,也可用set集合特点
var arr = [2,3,4,5,4,3,2,3,2]
for(i=0;i<=arr.length;i++){
console.log(arr[i])
for(j=i+1;j<=arr.length;j++){
if(arr[i]==arr[j]){
arr.splice(j,1)
}
}
}
22、js对象
对象,是一种复合数据类型,可以保存多个不同数据类型的属性
对象就像一个塑料袋,把不同数据类型的属性封装到一起,使其之间具有联系
对象的分类
内建对象:
在ES中定义的,Math,String,Function,Number
宿主对象:
在JS运行环境中提供,BOM,DOM
自定义对象:
开发自己定义
怎么使用对象呢
1、创建对象 var obj = new Object()
2、给对象赋值 obj.name = "wl"
3、取对象的值 obj.属性名
4、修改对象的属性值 obj.属性名 = 属性值
5、删除对象的属性 delete obj.属性名
对象的属性名定义,可以是任意命名
对象与变量的存储
变量存在栈内存中,存变量与值
对象存在堆内存,在堆内存开辟存储空间,定义的对象引用在栈内存存储新建的对象的指向地址,指向存放对象的堆内存
obj[propName]= value 使用['属性名']的方式
23、异步编程实现方法
1)回调函数
优点:简单、容易理解缺点:不利于维护、代码耦合高2)事件监听
优点:容易理解,可以绑定多个事件,每个事件可以指定多个回调函数缺点:事件驱动型,流程不够清晰3)发布/订阅(观察者模式)
类似于事件监听,但是可以通过‘消息中心’,了解现在有多少发布者,多少订阅者4)promise 对象
这个promise可以解决异步的问题,本身不能说promise是异步的 ,把一层一层向内嵌套调用的方法,给拉成一串连续调用的方法,promise成为js的原生的内容,具体使用的时候,要包装一下,使用第三方,一些浏览器不支持它
优点:可以利用 then 方法,进行链式写法;可以书写错误时的回调函数promise是用来解决两个问题的:
1.回调,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
2.promise可以支持多并发的请求,获取并发请求中的数据
缺点:1)无法取消Promise,一旦新建它就会立即执行,无法中途取消
2)如果不设置回调函数,Promise内部抛出的错误,不会反映到外部
3)当处于pending(等待)状态时,无法得知目前进展到哪一个阶段,是刚刚开始还是即将
const promise = new Promise((resolve,reject) => {
let num = Math.random();
console.log(num);
if(num>0.5){
resolve("num="+num);
}else {
reject("num="+num);
}
});
promise.then(msg = > {
alert("success:"+msg);
}).catch(msg =>{
alert("error:"+msg);
})
5)Generator函数
优点:函数体内外的数据交换、错误处理机制缺点:流程管理不方便6)await和async函数
await关键字
1)await只能在async函数内部使用:不能放在普通函数里面,否则会报错;
2)await关键字后面跟Promise对象:在Pending状态时,相应的协程会交出控制权,进入等待状态,这是协程的本质;不加 return
3)await是async wait的意思: wait的是resolve(data)的消息,并把数据data返回,比如下面代
码中,当Promise对象由Pending变为Resolved的时候,变量a就等于data,然后再顺序执行下面的语句console.log(a),这真的是等待,真的是顺序执行,表现和同步代码几乎一模一样;
async init(){
const params = {
pageLength: this.page.pageLength,
flag: this.page.flag,
rowKey: this.page.rowKey,
spacecraftId: this.spacecraft.id
}
let {data, code, message} = await driftPYHList(params);
if(code === 200){
this.table.data = data.list;
// this.dataLength = data.list.length;
}
},
注:什么是单线程,和异步的关系?
js单线程
因为JS里面有可视的Dom,如果是多线程的话,这个线程正在删除DOM节点,另一个线程正在编辑Dom节点,导致浏览器不知道该听谁的,为了避免DOM渲染冲突
JS运行机制
1、首先判断JS是同步还是异步,同步就进入主进程,异步就进入event table
2、异步任务在event table中注册函数,当满足触发条件后,被推入event queue
3、同步任务进入主线程后一直执行,直到主线程空闲时,才会去event queue中查看是否有可执行
的异步任务,如果有就推入主进程中
以上三步循环执行,这就是事件循环event loop
解决方案:异步
24、如何解决跨域浏览器的同源策略:协议、端口、域名必须完全一致,只要一个不一样,就会跨域
有三种解决方案:
1、JSONP:利用动态创建script标签请求后端接口地址,然后传递callback参数,后端接收callback。经过处理,返回callback函数调用的形式,callback中的参数就是json
2、CROS(跨域资源共享):由后端工程师设置后端代码来实现html" class="superseo">前端跨域请求
3、服务器代理:VUE3中有proxyTable配置跨域
4、nodejs中间件代理跨域
var script = document.createElement('script'); //创建script标签
function getData(data) { //设置回调函数
console.log('data');
}
script.src = "http://localhost:3000?callback=getData";//设置script的src属性,设置请求地址
document.body.appendChild(script); //让script生效
注:请解释JSONP的工作原理,以及它为什么不是真正的AJAX?
JSONP(JSON with Padding)是一个简单高效的跨域方式,HTML中的script标签可以加载并执行其他域的javascript,于是我们可以通过script标记来动态加载其他域的资源,例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函数,pageB加载完之后会执行pageA中定义的函数,所需要的数据会以参数的形式传递给该函数。JSONP易于实现,但是也会存在一些安全隐患,如果第三方的脚本随意地执行,那么它就可以算改页面内容,截获敏感数据,但是在受信任的双方传递数据,JSONP是非常合适的选择。
AJAX是不跨域的,而JSONP是一个是跨域的,还有就是二者接收参数形式不一样!
let proxyObj= {}
proxyObj['/']={
ws:false, //websocket
target:'http://localhost:8081',
changeOrigin:true, //发送请求头host会被设置target
pathRewrite:{ //不重写请求地址
'^/':'/'
}
}
module.exports={
devServer:{
host:'localhost',
port:8080,
proxy:proxyObj
}
}
25、Global
1、特点:全局变量,这个Global中封装的方法不需要对象就可以直接调用。方法名();
2、方法:
encodeURI():url编码 decodeURI():url解码
encodeURIComponent():url编码 decodeURIComponent():url解码
parseInt();将字符串转为数字
逐一判断每一个字符是否是数字,直到不是数字为止,将前边数字部分转为number
isNaN():判断一个值是否是NaN;
NaN六亲不认,连自己都不认,NaN参与的==比较全为false
eval() //将JS字符串,并把它作为脚本代码来执行
var str ="cdsf";
var encode = encodeURI(str);
document.write(encode+"
");
var decode = decodeURI(encode);
document.write(decode+"
");
26、Unicode utf-8
Unicode给每个字符都定义了对应的编码,编码范围 0x000000-0x10FFFF,有110多万
在JS中的用法:\u编码:是16进制 \u2620
在网页中的用法:编码:编码是10进制 ☠
必须把unicode从16进制转化为10进制,
27、严格模式的限制 变量必须声明后再使用函数的参数不能有同名属性,否则报错不能使用 with 语句禁止 this 指向全局对象 28、性能优化减少 HTTP 请求数
减少 DNS 查询
使用 CDN
避免重定向
图片懒加载
减少 DOM 元素数量
减少 DOM *** 作
使用外部 JavaScript 和 CSS
压缩 JavaScript、CSS、字体、图片等
优化 CSS Sprite
使用 iconfont
多域名分发划分内容到不同域名
尽量减少 iframe 使用
避免图片 src 为空
把样式表放在 link 中
把 JavaScript 放在页面底部
29、负载均衡单台服务器共同协作,不让其中某一台或几台超额工作,发挥服务器的最大作用
http 重定向负载均衡:调度者根据策略选择服务器以 302 响应请求,缺点只有第一次有效果,后续 *** 作维持在该服务器 dns 负载均衡:解析域名时,访问多个 ip 服务器中的一个(可监控性较弱)原因 - 避免 DOM 渲染的冲突
反向代理负载均衡:访问统一的服务器,由服务器进行调度访问实际的某个服务器,对统一的服务器要求大,性能受到 服务器群的数量
30、什么是执行栈,什么是执行上下文?1)执行上下文分为:
①全局执行上下文
创建一个全局的window对象,并规定this指向window,执行js的时候就压入栈底,关闭浏览器的时候才d出
②函数执行上下文
每次函数调用时,都会新创建一个函数执行上下文
执行上下文分为创建阶段和执行阶段
*创建阶段:函数环境会创建变量对象:arguments对象(并赋值)、函数声明(并赋值)、变量声明(不赋值),函数表达式声明(不赋值);会确定this指向;会确定作用域
*执行阶段:变量赋值、函数表达式赋值,使变量对象编程活跃对象
③eval执行上下文
2)执行栈:
首先栈特点:先进后出
当进入一个执行环境,就会创建出它的执行上下文,然后进行压栈,当程序执行完成时,它的执行上下文就会被销毁,进行d栈。
栈底永远是全局环境的执行上下文,栈顶永远是正在执行函数的执行上下文
只有浏览器关闭的时候全局执行上下文才会d出
31、JS 中的常用的继承方式原型继承、组合继承、寄生组合继承、ES6的extend
原型继承
把父类的实例作为子类的原型 缺点:子类的实例共享了父类构造函数的引用属性 不能传参
var person = {
friends: ["a", "b", "c", "d"]
}
var p1 = Object.create(person)
p1.friends.push("aaa")
组合继承
在子函数中运行父函数,但是要利用call把this改变一下, 再在子函数的prototype里面new Father() ,使Father的原型中的方法也得到继承,最后改变Son的原型中的constructor
缺点:调用了两次父类的构造函数,造成了不必要的消耗,父类方法可以复用 优点可传参,不共享父类引用属性
function Father(name) {
this.name = name
this.hobby = ["篮球", "足球", "乒乓球"]
}
Father.prototype.getName = function () {
console.log(this.name);
}
function Son(name, age) {
Father.call(this, name)
this.age = age
}
Son.prototype = new Father()
Son.prototype.constructor = Son
var s = new Son("ming", 20)
console.log(s);
寄生组合继承
function Father(name) {
this.name = name
this.hobby = ["篮球", "足球", "乒乓球"]
}
Father.prototype.getName = function () {
console.log(this.name);
}
function Son(name, age) {
Father.call(this, name)
this.age = age
}
Son.prototype = Object.create(Father.prototype)
Son.prototype.constructor = Son
var s2 = new Son("ming", 18)
console.log(s2);
extend
子类只要继承父类,可以不写 constructor ,一旦写了,则在 constructor 中的第一句话,必须是 super 。
class Son3 extends Father {
constructor(y) {
super(200) // super(200) => Father.call(this,200)
this.y = y
}
}
32、宏任务和微任务,如何执行
执行一个宏任务,过程中如果遇到微任务,就将其放到微任务的【事件队列】里
当前宏任务执行完成后,会查看微任务的【事件队列】,并将里面全部的微任务依次执行完
重复以上2步骤,结合event loop(1) event loop(2) ,就是更为准确的JS执行机制了。
微任务与宏任务都是异步,微任务优先级高
1)
宏任务:script、setTimeOut、setInterval、setImmediate、requrestAnimationFrame
1.宏任务所处的队列就是宏任务队列
2.第一个宏任务队列中只有一个任务:执行主线程的js代码
3.宏任务可以有多个
4.宏队列任务执行完后,先查看微任务队列并将其执行完;如果没有查看是否有宏任务队列
微任务:promise.then、process.nextTick、Object.observe、MutationObserver
1.微任务所处的队列就是微任务队列
2.只有一个微任务队列
3.在上一个任务队列执行定毕后如果有微任务队列就会执行微任务队列中的所有任务
注意:Promise是同步任务
2)怎么执行的
执行宏任务script,
进入script后,所有的同步任务主线程执行
所有宏任务放入宏任务执行队列
所有微任务放入微任务执行队列
先清空微任务队列,
再取一个宏任务,执行,再清空微任务队列
依次循环
33、exports和module.exports有什么区别?导出方式不一样
exports.xxx='xxx'
module.export = {}
exports是module.exports的引用,两个指向的是用一个地址,而require能看到的只有module.exports
34、JS模块包装格式,ES6和commonjs的区别commonjs:同步运行,不适合前端
AMD:异步运行,异步模块定义,主要采用异步的方式加载模块,模块的加载不影响后面代码的执行。所有依赖这个模块的语句都写在一个回调函数中,模块加载完毕,再执行回调函数
CMD:异步运行,seajs 规范
ES6和commonjs的区别
commonjs模块输出的是值的拷贝,而ES6输出的值是值的引用
commonjs是在运行时加载,是一个对象,ES6是在编译时加载,是一个代码块
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)