javascript常见知识点汇总

从输入网址到渲染完成经历了哪些过程?

  1. 输入网址,先经过DNS解析域名为IP地址,
  2. 与WEB服务器创建TCP连接
  3. 向web服务器发送http请求,服务器响应请求,返回指定url数据
  4. 浏览器加载web服务器返回的数据及解析html源文件
  5. 生成DOM树,解析css和js,渲染页面。

数组去重

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原型和原型链

js原型

JS中每一个函数都存在有一个原型对象属性prototype。而且全部函数的默认原型都是Object的实例。
css

js原型链

每一个继承父函数的子函数的对象都包含一个内部属性_proto_。该属性包含一个指针,指向父函数的prototype。若父函数的原型对象的_proto_属性为再上一层函数。在此过程当中就造成了原型链。
html

这个知识点,能够查看 juejin.im/post/5d0c78…es6

js数据类型

js基本数据类型

String、Number 、Boolean、Undefined、Null、Symbolweb

js引用数据类型

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;
复制代码

闭包中的 this 对象

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复制代码

实现一个简单的Promise

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关键字会进行以下操做

  1. 建立一个空对象,构造函数中的this指向这个空对象
  2. 连接该对象到另外一个对象(即设置该对象的__proto__为构造函数的prototype)
  3. 执行构造函数,将构造函数内的this做用域指向1步骤中建立的空对象{}
  4. 若是构造函数有返回值,则return返回值,不然return空对象obj

根据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 //若是构造函数返回的不是一个对象,返回建立的新对象
}复制代码

写一个方法,实现sum(2,3)和sum(2)(3)可以正常工做

第一种方法

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();
         }
    }
}复制代码

Session 和 Cookie 

Cookie

服务器经过Set-Cookie头给客户端一串字符串

客户端每次访问相同域名的网页时,必须带上这段字符串

客户端要在一段时间内保存这个Cookie

Cookie默认在用户关闭页面后就失效,后台代码能够任意设置Cookie的过时时间

大小大概在4kb

Session

将SessionID(随机数)经过Cookie发给客户端

客户端访问服务器时,服务器读取SessionID

服务器有一块内存(哈希表)保存了全部session

经过SessionID能够获得对应用户的隐私信息,如:id email

这块内存(哈希表)就是服务器上的全部session

通常来讲,Session是基于Cookie来实现的

null和undefined的区别

null是一个被分配的值,设置为null的变量意味着其无值。而undefined则是某个变量虽然声明了变量,可是还没进行过任何赋值。

相关文章
相关标签/搜索