如何处理浏览器的断网情况?

一、new操作符的几个作用:

new操作符返回一个对象,所以我们需要在内部创建一个对象
这个对象,也就是构造函数中的this,可以访问到挂载在this上的任意属性
这个对象可以访问到构造函数原型链上的属性,所以需要将对象与构造函数链接起来
返回原始值需要忽略,返回对象需要正常处理

二、new操作符的特点:

new通过构造函数Test创建处理的实例可以访问构造函数中的属性也可以访问构造函数原型链上的属性,所以:通过new操作符,实例与构造函数通过原型链连接了起来
构造函数如果返回原始值,那么这个返回值毫无意义
构造函数如果返回对象,那么这个返回值会被正常的使用,导致new操作符没有作用

instanceof的原理

instanceof 用来检测一个对象在其原型链中是否存在一个构造函数的 prototype 属性

function instanceOf(left,right) {
let proto = left.proto;
let prototype = right.prototype
while(true) {
if(proto === null) return false
if(proto === prototype) return true
proto = proto.proto;
}
}
复制代码Promise A+规范原理
在面试中高级前端时。要求被手写Promise A+规范源码是必考题了。如果想详细了解,请参考 一步步教你实现Promise/A+ 规范 完整版
class Promise {
constructor(executor) {
this.status = ‘pending’ // 初始化状态
this.value = undefined // 初始化成功返回的值
this.reason = undefined // 初始化失败返回的原因

    // 解决处理异步的resolve
    this.onResolvedCallbacks = [] // 存放所有成功的resolve
    this.onRejectedCallbacks = [] // 存放所有失败的reject

    /**
     * @param {*} value 成功返回值
     * 定义resolve方法
     * 注意:状态只能从pending->fulfilled和pending->rejected两个
     */
    const resolve = (value) => { 
        if(this.status === 'pending') {
            this.status = 'fulfilled' // 成功时将状态转换为成功态fulfilled
            this.value = value // 将成功返回的值赋值给promise
            // 为了解决异步resolve以及返回多层promise
            this.onResolvedCallbacks.forEach(fn => {
                fn() // 当状态变为成功态依次执行所有的resolve函数
            })
        }
    }
    const reject = (reason) => {
        if(this.status === 'pending') {
            this.status = 'rejected' // 失败时将状态转换为成功态失败态rejected
            this.reason = reason // 将失败返回的原因赋值给promise
            this.onRejectedCallbacks.forEach(fn => {
                fn() // 当状态变为失败态依次执行所有的reject函数
            })
        }
    }
    executor(resolve, reject) // 执行promise传的回调函数
}
/**
 * 定义promise的then方法 
 * @param {*} onFulfilled 成功的回调
 * @param {*} onRejected 失败的回调
 */
then(onFulfilled, onRejected) {
    // 为了解决then方法返回Promise的情况
    const promise2 = new Promise((resolve, reject) => {
        if(this.status === 'fulfilled') { // 如果状态为fulfilled时则将值传给这个成功的回调
            setTimeout(() => {
                const x = onFulfilled(this.value) // x的值有可能为 promise || 123 || '123'...
                // 注意:此时调用promise2时还没有返回值,要用setTimeout模拟进入第二次事件循环;先有鸡先有蛋
                resolvePromise(promise2, x, resolve, reject) 
            }, 0)
        }
        if(this.status === 'rejected') {
            setTimeout(() => {
                const x = onRejected(this.reason) // 如果状态为rejected时则将视频的原因传给失败的回调
                resolvePromise(promise2, x, resolve, reject) 
            }, 0)
        }
        if(this.status === 'pending') { // 记录-》解决异步
            this.onResolvedCallbacks.push(() => {
                setTimeout(() => {
                    const x = onFulfilled(this.value)
                    resolvePromise(promise2, x, resolve, reject) 
                }, 0)
            })
            this.onRejectedCallbacks.push(() => {
                setTimeout(() => {
                    const x = onRejected(this.reason)
                    resolvePromise(promise2, x, resolve, reject) 
                }, 0)
            })
        }
    })
    return promise2; // 解决多次链式调用的问题
}

}

const resolvePromise = (promise2, x, resolve, reject) => {
// console.log(promise2, x, resolve, reject)
if(promise2 === x) { // 如果返回的值与then方法返回的值相同时
throw TypeError(‘循环引用’)
}
// 判断x是不是promise;注意:null的typeof也是object要排除
if(typeof x === ‘function’ || (typeof x === ‘object’ && x !== null)) {
try {
const then = x.then // 获取返回值x上的then方法;注意方法会报错要捕获异常;原因111
if(typeof then === ‘function’) { // 就认为是promise
then.call(x, y => {
// resolve(y)
// 递归解析 ; 有可能返回多个嵌套的promise
resolvePromise(promise2, y, resolve, reject)
}, r => {
reject®
})
}
} catch(e) {
reject(e)
}
} else {
resolve(x);
}
}
module.exports = Promise;
复制代码JS数组
去重

普通项

let arr2 = [1, 2, 3, 2, 33, 55, 66, 3, 55];
第一种:
let newArr = [];
arr2.forEach(item => {
if(newArr.indexOf(item) == ‘-1’) {
newArr.push(item);
}
})
console.log(newArr);

// (6) [1, 2, 3, 33, 55, 66]
复制代码第二种:
let newArr = […new Set(arr2)];
console.log(newArr);

// (6) [1, 2, 3, 33, 55, 66]
复制代码注意:Array.from()、filter()、for()等方法都可以完成上面数组去重。

对象项

let arr1 = [
{id: 1, name: ‘汤小梦’},
{id: 2, name: ‘石小明’},
{id: 3, name: ‘前端开发’},
{id: 1, name: ‘web前端’}
];
复制代码实现方法:
const unique = (arr, key) => {
return […new Map(arr.map(item => [item[key], item])).values()]
}
console.log(unique(arr1, ‘id’));

// [
{id: 1, name: “web前端”},
{id: 2, name: “石小明”},
{id: 3, name: “前端开发”}
]
复制代码合并
let arr3 = [‘a’, ‘b’]
let arr4 = [‘c’, ‘d’]
复制代码方法一:ES5
let arr5 = arr3.concat(arr4);
console.log(arr5);

// [‘a’, ‘b’, ‘c’, ‘d’]
复制代码方法一:ES6
let arr6 = […arr3, …arr4];
console.log(arr6);

// [‘a’, ‘b’, ‘c’, ‘d’]
复制代码展平
let arr7 = [1, 2, [3, 4], [5, 6, [7, 8, 9]]];
复制代码第一种:
let arrNew = arr7.flat(Infinity);
console.log(arrNew);

// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码第二种:
let arrNew = arr7.join().split(’,’).map(Number);
console.log(arrNew);

// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码第三种:
let arrNew = arr7.toString().split(’,’).map(Number);
console.log(arrNew);

// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码第四种:
const flattern = (arr) => {
const result = []
arr.forEach((item) => {
if (Array.isArray(item)) {
result.push(…flattern(item))
} else {
result.push(item)
}
})
return result
}
flattern(arr7);

// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码第五种:
function flatten(arr) {
return [].concat(
…arr.map(x => Array.isArray(x) ? flatten(x) : x)
)
}
flattern(arr7);

// (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
复制代码是否为数组
let arr = []
复制代码第一种:instanceof
console.log(arr instanceof Array)
复制代码第二种:constructor
console.log(arr.constructor === Array)
复制代码第三种:判断对象是否有 push 等数组的一些方法
console.log(!!arr.push && !!arr.concat)
复制代码第四种:toString
console.log(Object.prototype.toString.call(arr) === ‘[object Array]’)
复制代码第五种:Array.isArray
console.log(Array.isArray(arr))
复制代码注意:第五种方式最优~
冒泡排序
let arr = [1, 44, 6, 77, 3, 7, 99, 12];
复制代码
冒泡排序算法的原理如下:

比较两个相邻的元素,若前一个比后一个大,则交换位置
第一轮的时候最后一个元素应该是最大的一个
对所有的元素重复以上的步骤,除了最后一个

function bubbleSort(arr) {
for(let i=0; i<arr.length; i++) {
for(let j=0; j<arr.length - i - 1; j++) {
if(arr[j+1] < arr[j]) {
let temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort(arr));

// [ 1, 3, 6, 7, 12, 44, 77, 99 ]
复制代码注意:最后一个元素不用比较。
快速排序
let arr = [1, 44, 6, 77, 3, 7, 99, 12];
复制代码
快速排序算法的原理如下:

找基准(一般是以中间项为基准)
遍历数组,小于基准的放在left,大于基准的放在right
递归

function quickSort(arr) {
if(arr.length <= 1) return arr;
let mid = Math.floor(arr.length / 2);
let midItem = arr.splice(mid, 1)[0];
let leftArr = [];
let rightArr = [];
for(let i=0; i<arr.length; i++) {
let current = arr[i];
if(current >= midItem) {
rightArr.push(current);
} else {
leftArr.push(current);
}
}
return quickSort(leftArr).concat([midItem], quickSort(rightArr));
}

console.log(quickSort(arr));

// [ 1, 3, 6, 7, 12, 44, 77, 99 ]
复制代码总结
上面总结我面试或面试别人常见的CSS、JS部分手写原理题。希望有小伙伴需要的请认真思考阅读,必有收获。希望您取得满意的offer~❤️

发布了15 篇原创文章 · 获赞 0 · 访问量 842

猜你喜欢

转载自blog.csdn.net/srhgsr/article/details/105206579
今日推荐