let array = [1,1,2,3,3,4,4,5,6];
let arrays = new Set(array); //es6的set语法
console.log(arrays) //1,2,3,4,5,6复制代码
let abc= [2,1,5,4,3,9,7,8,10,20]
function sorts(a,b){
return b-a; 主要区别
}
abc.sort(sorts);
console.log(abc) // [20, 10, 9, 8, 7, 5, 4, 3, 2, 1]
复制代码
let abc= [2,1,5,4,3,9,7,8,10,20]
function sorts(a,b){
return a-b; //主要区别
}
abc.sort(sorts);
console.log(abc) // [1, 2, 3, 4, 5, 7, 8, 9, 10, 20]复制代码
JS中每一个函数都存在有一个原型对象属性prototype。而且全部函数的默认原型都是Object的实例。
css
每一个继承父函数的子函数的对象都包含一个内部属性_proto_。该属性包含一个指针,指向父函数的prototype。若父函数的原型对象的_proto_属性为再上一层函数。在此过程当中就造成了原型链。
html
这个知识点,能够查看 juejin.im/post/5d0c78…es6
String、Number 、Boolean、Undefined、Null、Symbolweb
Object、Array、Function、Array、Data等面试
join(): arr.join(separator) ,separator参数为可选。将数组的元素组起一个字符串,以separator为分隔符,省略的话则用默认用逗号为分隔符,该方法只接收一个参数:即分隔符。数组
//不带参数
let arr = ["掘金",6,"大地王者","奋斗"]
console.log(arr.join());//掘金,6,大地王者,奋斗
//带参数
let arr = ["掘金",6,"大地王者","奋斗"]
console.log(arr.join("-"));//掘金-6-大地王者-奋斗复制代码
push()和pop():push(): 能够接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度。 pop():数组末尾移除最后一项,减小数组的 length 值,而后返回移除的项。promise
let arr = [1];
arr.push(2,3);
console.log(arr)//[1, 2, 3]
arr2.pop();
console.log(arr2) // [1, 2]
复制代码
shift() 和 unshift():shift():删除原数组第一项,并返回删除元素的值;若是数组为空则返回undefined 。 unshift:将参数添加到原数组开头,并返回数组的长度。列子可参考push()和pop()浏览器
reverse():反转数组项的顺序。bash
concat():将参数添加到原数组中。这个方法会先建立当前数组一个副本,而后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的状况下,它只是复制当前数组并返回副本。此方法也能够用于数组的合并服务器
let arr = [1,2,3]
let arr1 = arr6.concat(5,6,7)
console.log(arr1) //[1, 2, 3, 5, 6, 7]
复制代码
slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法能够接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的状况下, slice()方法返回从该参数指定位置开始到当前数组末尾的全部项。若是有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
splice():能够实现删除、插入和替换。
删除:能够删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。例如, splice(0,2)会删除数组中的前两项。
插入:能够向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。例如,splice(2,0,4,6)会从当前数组的位置 2 开始插入4和6。
替换:能够向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数没必要与删除的项数相等。例如,splice (2,1,4,6)会删除当前数组位置 2 的项,而后再从位置 2 开始插入4和6。
splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,若是没有删除任何项,则返回一个空数组。
map() (ES5新增):方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。不会对空数组进行检测。不会改变原始数组。参数接收的是一个方法,Array.map(callback);
const arr = [1, 3, 4, 5, 6, 7, 8, 10];
const res = arr.map((num)=>{
return num * num; //[ 1, 9, 16, 25, 36, 49, 64, 100 ]
})
复制代码
filter() (ES5新增):方法建立一个新的数组,新数组中的元素是经过检查指定数组中符合条件的全部元素。数组。
var words = ['1', '2', '3', '14', '34', '56'];
const result = words.filter(word => word > 6);
console.log(result); //["14", "34", "56"]
复制代码
every() (ES5新增):判断数组中每一项都是否知足条件,只有全部项都知足条件,才会返回true。
some() (ES5新增):判断数组中是否存在知足条件的项,只要有一项知足条件,就会返回true。
有关数组的更多用法,能够查看: developer.mozilla.org/en-US/docs/…
闭包是一个定义在一个函数(父函数)里面的函数,它拥有对父函数里面的变量的访问权。
一般,函数的做用域及其全部变量都会在函数执行结束后被销毁。可是,在建立了一个闭包之后,这个函数的做用域就会一直保存到闭包不存在为止。
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
// 释放对闭包的引用
add5 = null;
add10 = null;
复制代码
var name = "The Window";
var obj = {
name: "My Object",
getName: function(){
return function(){
return this.name;
};
}
};
console.log(obj.getName()()); // The Window
复制代码
obj.getName()()其实是在全局做用域中调用了匿名函数,this指向了window。这里要理解函数名与函数功能(或者称函数值)是分割开的,不要认为函数在哪里,其内部的this就指向哪里。匿名函数的执行环境具备全局性,所以其 this 对象一般指向 window。
应用闭包的主要场合是:设计私有的方法和变量。
闭包的缺点就是常驻内存会增大内存使用量,而且使用不当很容易形成内存泄露
function fun(n,o){
console.log(o);
return {
fun: function(m){
return fun(m,n);
}
};
}
var a = fun(0); // ?
a.fun(1); // ?
a.fun(2); // ?
a.fun(3); // ?
var b = fun(0).fun(1).fun(2).fun(3); // ?
var c = fun(0).fun(1); // ?
c.fun(2); // ?
c.fun(3); // ?
复制代码
undefined
0
0
0
undefined, 0, 1, 2
undefined, 0
1
1复制代码
function Promise(executor) {
//executor
this.status = 'pending'
this.reason = null
this.data = null
this.onFulFilledList = []
this.onRejectedList = []
const _this = this;
function resolve(data) {
if(_this.status == 'pending') {
_this.data = data
_this.status = 'onFulfilled'
_this.onFulFilledList.forEach(element => {
element(_this.data)
});
}
}
function reject(e) {
if(_this.status == 'pending') {
_this.reason = e
_this.status = 'rejected'
_this.onRejectedList.forEach(element => {
element(_this.reason)
})
}
}
executor(resolve, reject)
}
Promise.prototype.then = function(res, rej) {
const _this = this
if(_this.status=='onFulfilled') {
res(_this.data)
return
}
if(_this.status=='rejected') {
res(_this.reason)
}
if(_this.status=='pending'){
_this.onFulFilledList.push(res)
_this.onRejectedList.push(rej)
}
}复制代码
面试够用用版
function promise(constructor) {
let self = this;
self.status = "pending"; //定义状态改变前的初始状态
self.value = undefined; //定义状态为resolved的时候的状态
self.reason = undefined; //定义状态为rejected的时候的状态
function resolve(value) {
两个==="pending",保证了状态的改变是不可逆的
if(self.status === 'pending') {
self.value = value;
self.status = "resolved"
}
}
function reject(reason) {
两个==="pending",保证了状态的改变是不可逆的
if(self.status === "pending") {
self.readon = reason;
self.status = "rejected";
}
}
//捕获构造异常
try{
constructor(resolve, reject)
}catch(e){
reject(e)
}
}复制代码
同时,须要在 myPromise
的原型上定义链式调用的 then
方法:
promise.prototype.then = function(onFullfilled, onRejected) {
let self = this;
switch(self.status){
case "resolved":
onFullfilled(relf.value);
brack;
case "rejected":
onRejected(self.reason);
break;
default:
}
}复制代码
new关键字会进行以下操做
根据new的操做,实现代码
function new() {
let obj = {} //建立一个空对象
let [constructor, ...args] = [...arguments]
obj.__proto__ == constructor.prototype //设置该对象的__proto__为构造函数的prototype
let result = constructorr.apply(obj, args) //将构造函数的做用域指向建立的空对象上
if(result && (typeof (result) === 'object' || typeof(result) ==='function')) {
return result //若是构造函数执行的结构返回的是一个对象,那么返回这个对象
}
return obj //若是构造函数返回的不是一个对象,返回建立的新对象
}复制代码
第一种方法
function sum(x) {
if(arguments.length == 2) {
return arguments[0] + arguments[1];
}else{
return function(y) {
retunr x + y
}
}
}复制代码
第二种方法
function sum(x,y) {
if(y !== undefined){
return x + y;
}else{
return function (y) {
return x + y;
}
}
}复制代码
典型例子:鼠标连击触发
实现原理:当一次事件发生后,事件处理器要等必定阀值的时间,若是这段时间过去后,再也没有事件发生,就处理最后一次发生的事件
function debounce(fn, wait=50, immediate) {
let timer;
return function() {
if(immediate){
fn.apply(this, arguments)
}
if(timer) clearTimeout(timer)
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
}复制代码
能够理解为时间再一个管道中传输,加上这个节流阀之后,时间的流速就会减慢,实际上这个函数的就是如此,他能够将一个函数的调用频率在必定阀值内,例如1s,那么1s内这个函数必定不会被调用两次
function throttle(fn, wait) {
let prev = new Date();
return function() {
const args = arguments;
const now =-= new Date();
if(now - prev > wait) {
fn.apply(this.args)
pre = new Date();
}
}
}复制代码
服务器经过Set-Cookie头给客户端一串字符串
客户端每次访问相同域名的网页时,必须带上这段字符串
客户端要在一段时间内保存这个Cookie
Cookie默认在用户关闭页面后就失效,后台代码能够任意设置Cookie的过时时间
大小大概在4kb
将SessionID(随机数)经过Cookie发给客户端
客户端访问服务器时,服务器读取SessionID
服务器有一块内存(哈希表)保存了全部session
经过SessionID能够获得对应用户的隐私信息,如:id email
这块内存(哈希表)就是服务器上的全部session
通常来讲,Session是基于Cookie来实现的
null是一个被分配的值,设置为null的变量意味着其无值。而undefined则是某个变量虽然声明了变量,可是还没进行过任何赋值。