ES5中有6种:Number、String、Boolean、Undefined、Null、Object
ES6新增了Symbol
谷歌6版本bigInt:是指安全存储、操作大整数
基本数据类型:
1.基本类型的变量是存放在栈区的
2.基本类型的比较是值的比较
3.基本类型的赋值在赋值操作后,两个变量是相互不受影响的
引用数据类型:
1.引用类型在栈内存中保存的实际上是对象在堆内存中的引用地址
2.引用类型的比较是引用地址的比较
3.引用类型的赋值其实是保存在栈区引用地址的赋值,因此两个变量指向同一个对象,任何的操作都会相互影响
1.变量声明:新增了let和const
2.模板字符串
3.箭头函数
4.函数的参数默认值
5.解构赋值
6.for…of 和 for…in
7.引入了class关键字。
8.模块import,export(ES6中的类)
9.Promise
- var
① var定义的变量,没有块的概念,可以跨块访问。
②var定义的变量可以修改,如果不初始化会输出undefined,不会报错。
③重复声明不报错,视作修改。- let
①定义的变量,只能在块作用域里访问,不能跨块访问,但不影响作用域链。
②不能重复声明变量。- const
①const 定义的变量,一旦定义后,就不能修改,即 const 声明的为常量。使用时必须初始化(即必须赋值),只能在块作用域里访问。
②const 声明创建一个值的只读引用,只是变量标识符不能重新分配。所以,对象属性修改和数组元素变化不会出发 const 错误。
③声明对象类型一般使用 const,来规避误操作修改对象
回答模板
首先,var,let,const都是用来声明变量的关键字,他们之间的区别有:
1.var定义变量具备声明提升
2.var 声明变量可以重复声明,而 let 不可以重复声明
3.let和const必须先定义后使用,不能重复定义,拥有块级作用域,暂存性死区
4.const声明之后必须赋初始值,否则会报错,习惯上变量名大写,并且const定义的变量是只读变量,不能进行修改
方法一:遍历比较
var arr = [5, 5, 7, 7, 4, 9, 3, 1, 3];
var arr1 = [];
for (var i = 0; i < arr.length; i++) {
if (arr1.indexOf(arr[i]) == -1) {
arr1.push(arr[i]);
}
}
console.log(arr1);
方法二:set
var arr = [5, 5, 7, 7, 4, 9, 3, 1, 3];
var newarr = [... new Set(arr)]
console.log(newarr);
方法三:
var arr = [5, 5, 7, 7, 4, 9, 3, 1, 3];
var newarr = Array.from( new Set(arr))
console.log(newarr);
typeof
typeof它返回结果只有以下几种:
number,string,boolean,object,undfined,function
typeof在判断null时,返回值为object
判断应用类型时返回值为object,不能细致的具体到是哪一种 object。所以要 想区分对象、数组、null,单纯使用 typeof 是不行的。
instanceof
:instanceof 用于判断某个对象是否被另一个函数构造
Instanceof 运算符与 typeof 运算符相似,用于识别正在处理的对象的类型。与 typeof 方法不同的是,instanceof方法要求开发者明确地确认对象为某特定类型
var simpleStr = "This is a simple string";
var myString = new String();
var newStr = new String("String created with constructor");
var myDate = new Date();
var myObj = {};
var myNonObj = Object.create(null);
// 返回 false, simpleStr 并不是对象
simpleStr instanceof String;
// 返回 true
myString instanceof String;
// 返回 true
newStr instanceof String;
// 返回 true
myString instanceof Object;
// 返回 true
myObj instanceof Object;
// 返回 true
({}) instanceof Object;
// 返回 false, 一种创建非 Object 实例的对象的方法
myNonObj instanceof Object;
// 返回 false
myString instanceof Date;
// 返回 true
myDate instanceof Date;
// 返回 true
myDate instanceof Object;
// 返回 false
myDate instanceof String;
Object.prototype.toString.call()
Object.prototype.toString.call(null);// ”[object Null]”
Object.prototype.toString.call(undefined);// ”[object Undefined]”
Object.prototype.toString.call(“abc”);// ”[object String]”
Object.prototype.toString.call(123);// ”[object Number]”
Object.prototype.toString.call(true);// ”[object Boolean]”
箭头函数是匿名函数,ES5匿名函数的语法糖,并且没有自己的this,arguments
它的优点是:
(1)简洁的语法、
(2)隐式返回,如 下面的代码可以去掉return,代码移到一行,减少代码量
(3)解决了this的指向问题,原生的写法this指向的是调用者,箭头函数this绑定的是定义时的那个对象。如果有对象嵌套的情况,则this绑定到最近的一层对象上
箭头函数this不是指向 window,而是父级(指向是可变的)
箭头函数不能用作构造函数,因为它没有自己的 this,无法实例化。
因为箭头函数没有自己的 this,所以箭头函数内也不存在 arguments 对象。
可以通过bind修改this指向,普通函数通过apply,call来修改this指向
call、apply、bind的作用是改变this的指向,也就是函数执行时的上下文
apply 接收两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组形式传入。改变this指向后原函数会立即执行,且方法只是临时改变this指向一次。当第一个参数是Null、undefined时,默认指向window
fn1.apply(想要将this指向哪里, [函数实参1, 函数实参2]);
call 与apply用法很像,不同的是从第二个参数是一个参数列表不是数组
fn1.call(想要将this指向哪里, 函数实参1, 函数实参2);
bind方法创建一个新的函数,当这个新的函数被调用时,其 this 置为提供的值,其参数列表前几项,置为创建时指定的参数序列
首先,this是函数的内置对象
1.普通函数执行,内部this默认是window,严格模式下是undefined
2.对象方法()执行,内部this是对象本身.
3.构造函数用new执行,内部this指向新创建的实例对象
4.箭头函数,箭头函数没有自己的this ,箭头函数中的this是箭头函数创建时当前上下文中的this。如果当前.上下文没有this就会继续向上寻找.
5.事件处理函数:函数中的this是当前元素本身
6.函数内部this被call,apply, bind强制修改,以修改后指向为准.
总结:箭头函数是创建时就已经确定了this,又由于箭头函数本身没有this,所以使用all等方法也无法改变其this指向,第一个参数将被忽略.普通函数则是执行时才明确this。
概念:函数嵌套函数,被嵌套的函数被称为闭包函数
作用:在一个函数体外,使用了函数的局部变量,是将函数内部和函数外部连接起来的桥梁。
实现:在主函数fun中定义内部变量(count)以及函数(funzi),在子函数funzi中使用主函数的内部变量(count),将子函数(funzi)作为fun的返回值,在外界通过全局变量(f)与(fun)的返回值绑定,从而延长了(funzi)的生命周期,使得(count)可以在外界使用
缺陷:打破了垃圾回收机制,延长了局部变量的生命周期,使用闭包有可能会造成内存泄漏
应用:闭包的应用:实现变量的私有化,事件防抖,事件节流,偏函数与柯里化,bind等等函数
区别 | cookie | localStorage | sessionStorage |
---|---|---|---|
生命周期 | 设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭 | 除非主动删除数据,否则数据永远不会消失,即使窗口或浏览器关闭 | 仅在当前会话下有效 |
存储大小 | 4kb | 5M | 5M |
数据与服务器之间的交互方式 | cookie的数据会自动的传递到服务器,服务器端也可以写cookie到客户端 | 不会自动把数据发给服务器,仅在本地保存 | 不会自动把数据发给服务器,仅在本地保存 |
易用性 | 源生的cookie接口不友好 ,需要程序员自己封装 | 源生接口可以接受亦可再次封装来对Object和Array有更好的支持 | 源生接口可以接受亦可再次封装来对Object和Array有更好的支持 |
// 存储Cookie
setCookie(key, value) {
var day = 1; // 缓存时间
var path = '/'; // 设置路径,在同一路径下的网页可以共享cookie,路径不同时,不可以访问
var date = new Date();
date.setDate(date.getDate() + day); //设置失效时间
document.cookie = encodeURIComponent(key) + '=' + encodeURIComponent(value) + ';expires=' + date + ';path=' + path;
},
// 获取Cookie
getCookie(key) {
var cookieStr = document.cookie;
var cookieArr = cookieStr.split("; ");
for (var i = 0; i < cookieArr.length; i++) {
var temp = cookieArr[i].split("=");
if (temp[0] === key) {
return decodeURIComponent(temp[1]);
}
}
},
// 删除Cookie
delCookie(key) {
var path = '/'
CookieUtils.setCookie(key, 1, -1, path);
},
1.js中有同步任务、异步任务两种.
2.同步任务在JS引擎线程执行,形成执行栈
3.执行栈中的同步任务在执行过程中遇到异步任务,异步任务被放入任务队列,等待执行
4.执行栈中的任务运行完成后(JS引擎空闲),从任务队列中读取异步任务,加入到执行栈,并执行
5.主线程不断重复上面的第三步
任务队列主要分为两种:宏任务,微任务.
当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件,然后再去宏任务队列中取出一个事件。同一次事件循环中,微任务永远在宏任务之前执行.
同步任务:在主线程上,排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务
异步任务:不进入主线程,而进入“任务队列”的任务,只有“任务队列” 通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行
防抖函数:是将多次执行变为最后一次执行,比如百度搜索
function debounce(func,time){
var timerid = null;
return function(){
if(timerid){
clearTimeout(timerid );
timerid = null;
}
timerid = setTimeout(()=>{
func();
},time)
}
}
节流函数 :是将多次执行变成每隔一段时间执行调用一次函数,而不是一触发事件就调用一次,这样就会减少资源浪费。
function throttle(func,time){
var timerid = null;//保存定时器id
return function(){
if(!timerid){//定时器若不存在,则创建定时器
timerid = setTimeout(()=>{
func();
clearTimeout(timerid );
timerid = null;
},time)
}
}
}
for of 和 for in都是用来遍历的属性
1、推荐在循环对象属性的时候使用 for…in,在遍历数组的时候的时候使用 for…of
2、二者都可以循环数组,for in 输出的是数组的index下标,而for of 输出的是数组的每一项的值。
3、for in 可以遍历对象,for of 不能遍历对象
forEach 和 map 的相同点 :
- 都是循环遍历数组中的每一项
- forEach 和 map 方法里每次执行匿名函数都支持 3 个参数,参数分别是 item(当前每一项),
index(索引值),arr(原数组)forEach 和 map 的不同点 :
- map有返回值,返回值是由map回调函数决定
- forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
- forEach() 的执行速度 < map() 的执行速度
会改变数组自身的方法: push, pop, shift, unshift, splice ,sort, reverse,
不会改变数组自身的方法: concat, join, slice, toString
ES5数组方法: forEach,map, every, some, filter, reduce, indexOf, lastIndexOf
ES6数组扩展: from, of, find, findIndex, includes
选取字符串: substr,substring ,slice
查询字符串: indexOf,includes, search,match
其他:split,replace ,charAt,toLowercase ,toUppercase ,trim
setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。
setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。
区别:
setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返
回的 ID 值可用作 clearInterval() 方法的参数
1.携带数据的方式: get使用url或cookie传参。而post将数据放在BODY中。
2.携带数据量: get的urI会有 长度上的限制,则post的数据则可以非常大。
3.数据安全性: post比get相对安全,因为数据在地址栏上不可见。
1、HTTP 是超文本传输协议,信息是明文传输,HTTPS 则是具有安全性的 SSL 加密传输协
议
2、HTTP 和 HTTPS 使用的是完全不同的连接方式,用的端口也不一样,前者是 80,后者
是 443
3、HTTP 的连接很简单,是无状态的。HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密
传输、身份认证的网络协议,比 HTTP 协议安全。
原型:在 JavaScript 中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript
的对象中都包含了一个” prototype”内部属性,这个属性所对应的就是该对象的原型,原型的主要作用就是为了实现继承与扩展对象
原型链:当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去
prototype 里找这个属性,这个 prototype 又会有自己的 prototype,于是就这样一直找下去,
也就是我们平时所说的原型链的概念
构造函数:请描述一下构造函数,实例对象原型对象三者之间的关系?
每个构造函数都可以通过prototype指向原型对象,原型对象通过constructor指向构造函数,实例对象通过__ proto__ 指向原型对象
1.原型链继承:通过原型对象实现继承
子类的原型对象=父类的实例化对象
缺陷:
function Parent1() {
this.name = 'parent1';
this.play = [1, 2, 3]
}
function Child1() {
this.type = 'child2';
}
Child1.prototype = new Parent1();
console.log(new Child1());
2.借用构造函数继承
缺陷:原型对象的属性无法完成继承
function Parent1(){
this.name = 'parent1';
}
Parent1.prototype.getName = function () {
return this.name;
}
function Child1(){
Parent1.call(this);
this.type = 'child1'
}
let child = new Child1();
console.log(child); // 没问题
console.log(child.getName()); // 会报错
3.混合继承:通过原型继承和借用构造方法继承,实现完善的继承
function Parent3 () {
this.name = 'parent3';
this.play = [1, 2, 3];
}
Parent3.prototype.getName = function () {
return this.name;
}
function Child3() {
// 第二次调用 Parent3()
Parent3.call(this);
this.type = 'child3';
}
// 第一次调用 Parent3()
Child3.prototype = new Parent3();
// 手动挂上构造器,指向自己的构造函数
Child3.prototype.constructor = Child3;
var s3 = new Child3();
var s4 = new Child3();
s3.play.push(4);
console.log(s3.play, s4.play); // 不互相影响
console.log(s3.getName()); // 正常输出'parent3'
console.log(s4.getName()); // 正常输出'parent3'
4.Es6继承: ES6中的继承就是通过类来实现的,通过class定义父类和子类,子类通过extends继承父类,通过super关键字访问和调用对象在父类上的方法(可以调用父类的构造方法,也可以调用父类的普通方法)
//定义父类
class Parent{
constructor(name,gender){
this.name = name;
this.gender = gender;
};
get(){
console.log("姓名:",this.name);
console.log("性别:",this.gender);
}
}
class Child extends Parent{
constructor(name,gender,age){
super(name,gender); //super必须在子类的this之前调用
this.age = age;
}
disp(){
console.log("年龄:",this.age)
}
change(){
console.log(this.name+'的性别是'+this.gender,'今年'+this.age)
}
}
var c1 = new Child('小红','女',20);
c1.get(); //姓名: 小红 性别: 女
c1.disp(); //年龄: 20
c1.change(); //小红的性别是女 今年20
for in:可以遍历数字,返回的是对应的key
for (let i in obj){
执行的代码块
}
Object.keys()、Object.values()、Object.entries()
Object.keys():返回包含对象键名的数组
Object.values():返回包含对象键值的数组
Object.entries():返回包含对象键名和键值的数组
let obj={
id:1,
name:'hello',
age:18
}
console.log(Object.keys(obj)) //['id','name','age']
console.log(Object.values()) //[1,'hello',18]
console.log(Object.entries()) //[['id',1],['name','hello'],['age',18]]
1.设置document domain读取非同源网页的Cookie
2 postMessage(),跨文档通信API.
3.JSONP,服务器与客户端跨源通信.
4.CORS ,跨域资源共享,服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的.
5.webpack本地代理,在webpack. config .js中配置本地代理proxy
6.websocket,实现了浏览器与服务器的全双工通信
7.Nginx反向代理,需 要搭建一个中转 nginx服务器,用于转发请求
方法一:使用for in遍历,加递归
let obj ={name:"hhh",age:18};
let newobj = {}
function fun(obj){
for(let key in obj){
if(obj.ket.typeof=="object"){
fun(obj.ket)
}else{
newobj.key=obj.key
}
}
}
方法二:JSON.parse()和JSON.stringify()
JSON.parse(JSON.stringify(obj))
阻止事件冒泡的方法:event.stopPropagation();
阻止默认行为: e.preventDefault()
内存泄漏指任何对象在您不再拥有或需要它之后仍然存在
闭包,定时器等等都会造成闭包
1、Promise是异步编程的一种解决方案
2、promise有 三种状态: pending(等待态),resolve(成功态),rejected(失败态);
3、状态一旦改变,就不会再变。
4、创造promise实例后,它会立即执行Promise用来解决传统异步回调出现的回调地狱问题.
5、promise构造函数是同步执行的,then方法是异步执行的
事件循环中分为宏任务队列和微任务队列
宏任务(macrotask):在新标准中叫 task
主要包括:script(整体代码),setTimeout,setInterval,setImmediate,I/O,ui rendering
微任务(microtask):在新标准中叫 jobs
主要包括:process.nextTick, Promise,MutationObserver(html5 新特性)
setTimeout、Promise、Async/Await 的区别
setTimeout 的回调函数放到宏任务队列里,等到执行栈清空以后执行
Promise.then 里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行
async 函数表示函数里面可能会有异步方法,await 后面跟一个表达式
async 方法执行时,遇到 await 会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行
ES6创建类:es6中所有的属性和方法都定义在constructor中
class Point{
constructor(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
}
toString(){
return '(' + this.x + ',' + this.y + ',' + this.z + ')';
}
}
let p = new Point(89,56,12);
console.log(p,typeof p,typeof Point,Point === Point.prototype.constructor);
ES5创建类
function Point(x,y,z){
this.x = x;
this.y = y;
this.z = z;
}
Point.prototype.toString = function(){
return '(' + this.x + ',' + this.y + ',' + this.z + ')';
}
var p = new Point(23,67,98);
console.log(p,typeof p,typeof Point,Point === Point.prototype.constructor);
先微后宏,所以先promise,后setTimeout
var str="aakjaahgaaayjaaabbbrfghe";
function unique(str) {
var obj={};
for(var i=0;i<str.length;i++){
if(obj[str[i]]){
obj[key]++;
}else{
obj[key]=1;//obj[w]=1
}
}
var arr = Object.keys(obj);
for(var i=0;i<arr.length;i++){
console.log(arr[i]+'出现次数为:'+obj[arr[i]])
}
}
unique(str)
持续更行中。。。