堆和栈的区别主要有五大点,分别是:
1、申请方式的不同。栈由系统自动分配,而堆是人为申请开辟;
2、申请大小的不同。栈获得的空间较小,而堆获得的空间较大;
3、申请效率的不同。栈由系统自动分配,速度较快,而堆一般速度比较慢;
4、存储内容的不同。栈在函数调用时,函数调用语句的下一条可执行语句的地址第一个进栈,然后函数的各个参数进栈,其中静态变量是不入栈的。而堆一般是在头部用一个字节存放堆的大小,堆中的具体内容是人为安排;
5、底层不同。栈是连续的空间,而堆是不连续的空间。
事件委托的好处
1、可以在批量子元素实现功能时,由父元素的事件体实现子元素功能。降低代码冗余,提高程序效率
2、可以为将来添加的元素提前绑定事件
arguments
1、arrguments:函数体内置对象,作用在函数体内。是一个伪数组(只能访问元素和length属性,其他API不能操作),保存着所有的实参
2、arrguments.callee:代表函数体本身
原型对象
1、原型对象是函数对象的一个属性-prototype,它保存着所有实例对象共享的属性和方法
2、当一个实例对象修改了同名的原型对象属性时,是不能实现的,等价于实例对象自己创建了一个同名属性
3、为什么实例对象可以访问原型对象的属性和方法:实例对象可以访问自己new出来的属性和方法,实例对象在创建时会生成一个__proto__属性,它指向原型对象的所有属性和方法
apply和call(多态)
1、都是修改this指向的
apply:函数对象:apply(被修改this指向的实例化对象,[原函数的参数1,参数2])
call:函数对象:call(被修改this指向的实例化对象,原函数的参数1,参数2)
apply,call,bind的异同
1、都是用来修改this指向的
2、apply和call是用来修饰有名函数,bind是用来修饰匿名函数
3、apply和call会直接调用该方法,bind会生成一个新的函数对象
4、apply的第二个参数必须是数组,call和bind第二个参数用逗号隔开
匿名函数
没有名字的函数
1、把一个函数当做一个变量赋值
let fun = function(){
alert("亲,我来自无名函数");
}
2、回调函数,一个被当作函数参数的函数
setInterval(function(){
console.log("heihei");
},1000);
3、作为函数的返回值
function f1(){
// let f2 = function(){
// }
// return f2;
return function(){
}
}
自运行
针对匿名函数,当匿名函数被定义时,可以被直接调用
//b.官方推荐
(function(){
console.log("嘿嘿嘿");
}());
闭包
概念:函数嵌套函数,被嵌套的函数称为闭包函数
闭包的作用:可以在函数的外部使用该函数内部的变量及柯里化函数
高级理解:1、类的公有和私有属性
2、柯里化函数
闭包的实现:一个函数内部定义一个变量,嵌套子函数,在子函数中操作这个变量,将子函数作为父函数的返回值,通过定义一个全局变量,和父函数的返回值(子函数)进行绑定,从而延长局部变量的生命周期
闭包的缺陷:延长了局部变量的生命周期
打破了原有的垃圾回收机制,大量使用闭包会导致内存泄露
function f1(){
var count = 0;
var f2 = function(){
++count;
return count;
}
return f2;
}
// f = f1() = f2 //绑定
let f = f1();
console.log(f());
console.log(f());
console.log(f());
//变形写法
function f1(){
var count = 0;
return function(){
return ++count;
}
}
let f = f1();
console.log(f());
console.log(f());
console.log(f());
柯里化函数:一个拥有一个参数,且返回值为一个函数的函数
作用:柯里化实际上是把简单的问题复杂化了,但是复杂的同时使得函数有更多的自由度
而这种对函数参数的自由处理,正式柯里化的核心
柯里化本质是降低通用性,提高适用性
// 柯里化思想
function regChecked(reg){
return function(str){
return reg.test(str);
}
}
//1.测试用户名
// 创建工具函数
let checkedUserName = regChecked(/^\D\w{5,17}$/);
console.log(checkedUserName("laowang"));
console.log(checkedUserName("111"));
console.log(checkedUserName("hahahahaah"));
//2.测试密码
//创建工具函数
let checkedUserPwd = regChecked(/^.{6,}$/);
console.log(checkedUserPwd("123"));
console.log(checkedUserPwd("454646"));
console.log(checkedUserPwd("hahahahaah"));
this的作用
概念:this是函数的内置对象,只能出现在函数的作用域内
1、作用于事件体函数时:表示触发该事件的元素
2、作用于构造函数时:表示new出来的对象
3、作用于普通函数(除了事件体函数和构造函数)时:表示调用该函数的对象(指向window)
4、作用于箭头函数时:代表其父元素的前缀
继承
1、子类吸收父类已有的属性和方法(拿来直接用),大大提高了代码的复用性
原型继承:依赖原型对象实现继承
缺陷:
1、一定要先实现继承关系,再为子类添加属性和方法
2、一旦继承关系实现,就无法修改原型对象的this指向
3、无法在子类对象构造时,初始化由父类派生的属性
unction Animal(name){
this.name = name;
}
Animal.prototype.eat = function(){
console.log("Animal eat");
}
function Human(id){
this.id = id;
}
Human.prototype = new Animal("老王");
Human.prototype.makeTools = function(){
console.log("Human makeTools");
}
2、借用构造方法继承(apply和call):
作用:可以在子类对象构造时,初始化由父类派生给子类的属性
缺陷:无法实现原型对象的继承
3、混合继承:1、通过apply和call实现属性的继承
2、通过原型对象继承,实现原型对象的属性和方法继承
4、ES6继承:
使用extends关键字:子类 extends 父类
super:借用父类的构造方法
typeof和intanceof的区别
1、都是用来判断数据类型的
2、typeof用来判断基本数据类型,判断引用数据类型时都会返回object
3、intanceof用来判断引用类型,并且满足兼容性规则。返回布尔值
值传递和引用传递
1、值传递:内置基本类型作为实参,单向传递,只能由实参改变形参,反之不行
2、引用传递:引用数据类型作为实参,双向传递,形参可以改变实参
深拷贝和浅拷贝
深浅拷贝只针对于引用类型
1、浅拷贝:只拷贝内容,不开辟新空间,两个对象共用一块空间地址
2、深拷贝:即拷贝数值,也开辟新空间,每个对象拥有独立的空间地址
本地存储
1、localstorage:本地永久存储,将数据存储在本地磁盘中,除非删除,否则一直存在
2、sessionstorage:本地临时存储,将数据存放在浏览器客户端内,页面关机就消失
getItem():获取本地存储数据
setItem():添加本地存储
removeItem():删除本地存储
clear():删除所有本地存储
key(index):返回列表对应下标的key值
cookie和localstorage、sessionstorage的区别
1、存储方式:
cookie的临时会话存储在浏览器中,会话结束就会消失
长生命周期的cookie存在本地磁盘中,到期或者删除会消失
localstorage是本地永久存储,存储在本地磁盘里,除非删除,否则一直存在
sessionstorage临时存储,存储在浏览器客户端中,页面关闭就会消失
2、储存大小:
cookie存储大小一般为4KB
本地存储大小一般为5mb
3、与服务器端的通信方:
cookie每次都携带在http头中,大量使用会影响性能
本地存储不参与和服务器的通信
4、易用性:
cookie的原生api不友好
本地存储的原生api可以接受,还可以再次封装来对Object和Array更好的支持
Object.defineproperty及双向绑定的原理
1、以前都是dom驱动,vue都是数据驱动
2、vue数据驱动,双向绑定原理,object.defineproperty
3、object.defineproperty是ES5的一个函数,为对象添加属性
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" value="">
</body>
</html>
<script>
let data = {
}
let oInput = document.querySelector("input");
Object.defineProperty(data, "content", {
get: function () {
return oInput.value;
},
set: function (v) {
oInput.value = v;
}
});
data.content = 9999;
</script>
proxy
1、语法:let proxy = new Proxy(被代理的目标对象,修饰符)
let data = {
name:"老王",
age:18,
fun:function(){
console.log(this);
},
hobby:["唱","跳","rap","你干嘛"]
}
let proxy = new Proxy(data,{
//set(目标对象,属性名,属性值,[代理对象])
set:function(target,property,value){
console.log("set");
// target[property] = value;
Reflect.set(target,property,value);
},
//get(目标对象,属性名,[代理对象])
get:function(target,property){
console.log("get");
//return target[property];
return Reflect.get(target,property);
}
});
// proxy.name = "老六";
// console.log(proxy.name);
// proxy.age = 88;
// console.log(proxy.age);
data.fun();
proxy.fun();
为什么要使用proxy替代Object.defineProperty
1、proxy可以对一个对象的所有属性添加get和set,而Object.defineProperty则需
要把每一个对象的属性都写出来
2、Object.defineProperty没有深度遍历,如果修改数组元素则不会触发get和set,但proxy可以
hasOwnProperty
1、作用:只遍历自身属性,不遍历原型链上的属性
let data = {
name:"蔡徐坤",
age:24
}
Object.prototype.a = 666;
//console.log(data.a);
//需求:只需要遍历自身的属性而不考虑原型链的属性?
//hasOwnProperty:只遍历自身的属性,不去遍历原型链上的属性
for(let index in data){
//对象.hasOwnProperty(属性值):是自身的属性返回true,是原型上的属性
//返回false
if(data.hasOwnProperty(index)){
console.log(data[index]);
}
}
Ajax
1、什么是Ajax
Ajax是一种网页异步交互技术。传统的网页需要更新内容时,必须要重载整个页面。通过Ajax异步交互技术,当需要更新页面局部内容时,无需重载整个页面就可以实现。前端通过Ajax与服务器少量的数据交换,可以使网页实现异步更新
2、为什么要使用Ajax
a.更自然,流畅的用户体验,对用户的操作及时响应
b.在不中断用户操作的情况下与web服务器通信
c.更灵敏的响应用户访问,实现接近于桌面应用程序的交互效果
d.通过局部更新页面降低网络流量,提高网络的使用效率
异步和同步
1、JS是单线程语言,为了解决同时出现多个任务引入了同步与异步技术
2、所有代码都消耗执行时间,异步代码有等待时间
3、同步代码按照顺序一步一步执行,必须前一步执行完毕,后一步才能继续执行
4、异步代码在执行时,如果遇到需要消耗等待时间的代码,则会先跳过该代码,先执行后续代码,直至代码消耗完等待时间再去执行
注意事项:优先执行同步代码,只有同步代码遵循自上而下的执行顺序
只要消耗等待时间的代码都是异步代码
5、常见的异步代码:a.定时器的回调函数
b.事件体
c.发请求和接相应(围绕着Ajax)
事件轮循机制
所有代码最终都要通过主线程编译,同步代码储存在执行栈,异步代码储存在任务队列
1、先执行栈的同步代码
2、异步模块有消耗完等待时间时,会告知主线程,准备进入执行状态
3、主线程等所有同步代码执行完成后,将把等待时间消耗完成的代码拉入主线程执行
异步代码又分为宏任务和微任务:
I/O、UI交互事件、setImmediate(node环境)
微任务大概包括:new promise().then(回调)、
MutationObserver(html5新特新)、Object.observe(已废弃)、
process.nextTick(node环境)
执行异步代码时,有微则先微,无微则宏
4、重复以上三步
Ajax步骤
1、创建Ajax核心对象–XMLHttpRequest
2、open
3、send
4、onreadystatechenage
5、返回信息—responseText
//1.掏手机--->创建ajax核心XMLHttpRequest对象
let xhr = new XMLHttpRequest();
//2.拨号-=->open
// xhr.open("请求的方式get/post","服务器文件地址",是否异步);
xhr.open("get","ajax.txt",true);
//3.发射--->send
xhr.send();
//4.等onreadystatechange事件
//异步
xhr.onreadystatechange = function(){
// 听见嘟嘟嘟嘟~~~
// 对方接通电话
if(xhr.status == 200 && xhr.readyState == 4){
//5.返回给你信息
//responseText服务器根据请求返回给前端的信息
fun(xhr.responseText);
}
}
function fun(resText){
console.log(resText);
}
Ajax的属性
1、readystate:是xhr对象的属性,发请求和接响应过程中的状态码
0:刚创建完xhr对象
1:调用完open方法准备发送
2:调用了send方法,将请求发送出去
3:数据发到了服务器
4:服务器接收完成解析返回响应
get和post的异同
1、post不能在url携带请求参数
2、post必须在open和send之间设置请求头
3、将请求参数写在send中
接口
1、什么是接口:接口的本质就是服务器文件地址0
2、接口四要素:a.接口地址
b.接口请求类型
c.请求参数
d.返回的数据格式
promise
1、什么是promise
promise是一个对象,该对象是一种异步处理机制。异步代码是无法决定执行顺序,当我们需要将异步代码按照一定顺序执行时,会使用回调函数的嵌套来解决。但回调函数的嵌套会形成回调地狱,为了解决回调地狱问题(其实是为了优化异步代码必须遵循先后顺序的写法),可以将函数调用的写法改为平级调用。
2、promise的功能
可以让回调函数不从主函数的参数位置传进来
3、promise的参数
promise有两个参数success和failed,这两个参数依然是回调函数。success是用来接收请求成功时的响应,failed是用来接收请求失败时的响应,可以不写
all和race
//1、all:一次发送多个请求,必须保证所有的请求都收到才会渲染页面
Promise.all([p1,p2,p3]).then(function(resText){
console.log(resText);
});
//2、race:一个页面的渲染,很多服务器都有相同的接口,为了效率一次可以发送多个请求,那个先返回就使用那个
Promise.race([p1,p2,p3]).then(function(resText){
console.log(resText);
});
async和await
async是修饰函数的关键字,await必须搭配async一起使用。async 函数返回的是一个promise 对象,await 表示等一下,代码就暂停到这里,不再向下执行了,它等什么呢?等后面的promise对象执行完毕,然后拿到promise resolve 的值并进行返回,返回值拿到之后,它继续向下执行
async是修饰函数的关键字,async和await基本是组合使用的,async用来声明一个异步方法,返回的是一个promise对象,如果要获取到对应的返回值,就需要使用.then方法
await只能在async方面的里面使用,让后面的执行语句或方法要等待当前await方法的结果后才能再执行。
跨域
跨域:A网站的页面去访问B网站的服务器文件
如果只需要知道某台电脑的ip,
以及文件名,难道就可以访问那台电脑所有内容?
同源策略:浏览器的一种安全机制,只能访问
a.同ip
b.同端口
c.同协议
的文件
实际需求中,很多地方就得跨域访问
如访问百度的搜索引擎,导航,天气预报,人工智能客服
跨域的解决方案
前端:jsonp
jsonp就是个名字,(叫啥都行),它是前端跨域的一种技巧(没有新语法),
可以实现跨域访问
怎么实现:
1.src属性自带跨域
2.script标签也是有src属性的
3.srcipt+src也可以跨域
4.前端写函数定义
后端模拟函数调用,通过参数返回响应的