前端面试手撕题
01.手撕instanceof
第一个参数是实例,第二个参数是构造函数
function myInstanceof(instance, object) {
let current = instance; //定义一个指针存储当前实例的位置
let target = object.prototype; //存储目标构造函数的原型对象
while(current) {
//指针指向null时说明原型链上没这个构造函数
if(current.__proto__ == target) {
//如果找到了,就返回true
return true;
} else {
//如果没找到,指针向后指
current = current.__proto__
}
}
//如果找到最后的null都没有,说明该实例不属于object所在原型链上任何一个原型对象
return false;
}
测试代码:
console.log([1,2,3] instanceof Array); //true
console.log(myInstanceof([1,2,3], Array)) //true
console.log([1,2,3] instanceof Object);//true
console.log(myInstanceof([1,2,3], Object)); //true
console.log([1,2,3] instanceof Function);//false
console.log(myInstanceof([1,2,3], Function)); //false
console.log([1,2,3] instanceof RegExp);//false
console.log(myInstanceof(/1/, RegExp)); //true
02.如何让 0.1+0.2 === 0.3
function withinError(left, right) {
return Math.abs(left-right) < Number.EPSILON;
}
console.log(withinError(0.1 + 0.2, 0.3)); //true
03.手撕new关键字
第一个参数是构造函数,第二个参数是实例化时的参数
function myNew(Fn, ...args) {
//1.判断传入的是否是一个函数
if(typeof Fn != 'function') return false;
//2.创建一个新对象,让该对象的__proto__指向构造函数的prototype
const obj = Object.create(Fn.ptototype);
//3.让Fn中的this指向这个新创建的对象,并给它们传值
let result = Fn.call(obj, ...args);
//4.如果构造函数写了返回值,要判断,如果是复杂数据类型,那么就返回该返回值
if(result && (typeof result === 'object' || typeof result === 'function')) {
return result;
}
//5.如果构造函数没有返回值、或有返回值但是简单数据类型,则返回新创建的对象
return obj;
}
04.手写原生ajax
<body>
<button>点击发送请求</button>
<div id="result"></div>
<script>
//获取button元素
const btn = document.querySelector('button');
const result = document.querySelector('#result');
btn.addEventListener('click', function() {
//1.创建对象
const xhr = new XMLHttpRequest();
//2.初始化