面试系列,前端面试js高频手写大全(1),前端编程基础班

function Person(name,age){

this.name=name

this.age=age

}

Person.prototype.sayHi=function(){

console.log(‘Hi!我是’+this.name)

}

let p1=new Person(‘张三’,18)

手动实现new

function create(){

let obj={}

//获取构造函数

let fn=[].shift.call(arguments)  //将arguments对象提出来转化为数组,arguments并不是数组而是对象    !!!这种方法删除了arguments数组的第一个元素,!!这里的空数组里面填不填元素都没关系,不影响arguments的结果      或者let arg = [].slice.call(arguments,1)

obj.proto=fn.prototype

let res=fn.apply(obj,arguments)    //改变this指向,为实例添加方法和属性

//确保返回的是一个对象(万一fn不是构造函数)

return typeof res===‘object’?res:obj

}

let p2=create(Person,‘李四’,19)

p2.sayHi()

细节:

[].shift.call(arguments)  也可写成:

let arg=[…arguments]

let fn=arg.shift()  //使得arguments能调用数组方法,第一个参数为构造函数

obj.proto=fn.prototype

//改变this指向,为实例添加方法和属性

let res=fn.apply(obj,arg)

10. 手写promise(常见promise.all, promise.race)

// Promise/A+ 规范规定的三种状态

const STATUS = {

PENDING: ‘pending’,

FULFILLED: ‘fulfilled’,

REJECTED: ‘rejected’

}

class MyPromise {

// 构造函数接收一个执行回调

constructor(executor) {

this._status = STATUS.PENDING // Promise初始状态

this._value = undefined // then回调的值

this._resolveQueue = [] // resolve时触发的成功队列

this._rejectQueue = [] // reject时触发的失败队列

// 使用箭头函数固定this(resolve函数在executor中触发,不然找不到this)

const resolve = value => {

const run = () => {

// Promise/A+ 规范规定的Promise状态只能从pending触发,变成fulfilled

if (this._status === STATUS.PENDING) {

this._status = STATUS.FULFILLED // 更改状态

this._value = value // 储存当前值,用于then回调

// 执行resolve回调

while (this._resolveQueue.length) {

const callback = this._resolveQueue.shift()

callback(value)

}

}

}

//把resolve执行回调的操作封装成一个函数,放进setTimeout里,以实现promise异步调用的特性(规范上是微任务,这里是宏任务)

setTimeout(run)

}

// 同 resolve

const reject = value => {

const run = () => {

if (this._status === STATUS.PENDING) {

this._status = STATUS.REJECTED

this._value = value

while (this._rejectQueue.length) {

const callback = this._rejectQueue.shift()

callback(value)

}

}

}

setTimeout(run)

}

// new Promise()时立即执行executor,并传入resolve和reject

executor(resolve, reject)

}

// then方法,接收一个成功的回调和一个失败的回调

function then(onFulfilled, onRejected) {

// 根据规范,如果then的参数不是function,则忽略它, 让值继续往下传递,链式调用继续往下执行

typeof onFulfilled !== ‘function’ ? onFulfilled = value => value : null

typeof onRejected !== ‘function’ ? onRejected = error => error : null

// then 返回一个新的promise

return new MyPromise((resolve, reject) => {

const resolveFn = value => {

try {

const x = onFulfilled(value)

// 分类讨论返回值,如果是Promise,那么等待Promise状态变更,否则直接resolve

x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)

} catch (error) {

reject(error)

}

}

}

}

const rejectFn = error => {

try {

const x = onRejected(error)

x instanceof MyPromise ? x.then(resolve, reject) : resolve(x)

} catch (error) {

reject(error)

}

}

switch (this._status) {

case STATUS.PENDING:

this._resolveQueue.push(resolveFn)

this._rejectQueue.push(rejectFn)

break;

case STATUS.FULFILLED:

resolveFn(this._value)

break;

case STATUS.REJECTED:

rejectFn(this._value)

break;

}

})

}

catch (rejectFn) {

return this.then(undefined, rejectFn)

}

// promise.finally方法

finally(callback) {

return this.then(value => MyPromise.resolve(callback()).then(() => value), error => {

MyPromise.resolve(callback()).then(() => error)

})

}

// 静态resolve方法

static resolve(value) {

return value instanceof MyPromise ? value : new MyPromise(resolve => resolve(value))

}

// 静态reject方法

static reject(error) {

return new MyPromise((resolve, reject) => reject(error))

}

// 静态all方法

static all(promiseArr) {

let count = 0

let result = []

return new MyPromise((resolve, reject) =>       {

if (!promiseArr.length) {

return resolve(result)

}

promiseArr.forEach((p, i) => {

MyPromise.resolve§.then(value => {

count++

result[i] = value

if (count === promiseArr.length) {

resolve(result)

}

}, error => {

reject(error)

})

})

})

}

// 静态race方法

static race(promiseArr) {

return new MyPromise((resolve, reject) => {

promiseArr.forEach(p => {

MyPromise.resolve§.then(value => {

resolve(value)

}, error => {

reject(error)

})

})

})

}

}

11. 手写原生AJAX

步骤

  1. 创建 XMLHttpRequest 实例

  2. 发出 HTTP 请求

  3. 服务器返回 XML 格式的字符串

  4. JS 解析 XML,并更新局部页面

不过随着历史进程的推进,XML 已经被淘汰,取而代之的是 JSON。

了解了属性和方法之后,根据 AJAX 的步骤,手写最简单的 GET 请求。

version 1.0:

myButton.addEventListener(‘click’, function () {

ajax()

})

function ajax() {

let xhr = new XMLHttpRequest() //实例化,以调用方法

xhr.open(‘get’, ‘https://www.google.com’)  //参数2,url。参数三:异步

xhr.onreadystatechange = () => {  //每当 readyState 属性改变时,就会调用该函数。

if (xhr.readyState === 4) {  //XMLHttpRequest 代理当前所处状态。

if (xhr.status >= 200 && xhr.status < 300) {  //200-300请求成功

let string = request.responseText

//JSON.parse() 方法用来解析JSON字符串,构造由字符串描述的JavaScript值或对象

let object = JSON.parse(string)

}

}

}

request.send() //用于实际发出 HTTP 请求。不带参数为GET请求

}

promise实现

function ajax(url) {

const p = new Promise((resolve, reject) => {

let xhr = new XMLHttpRequest()

xhr.open(‘get’, url)

xhr.onreadystatechange = () => {

if (xhr.readyState == 4) {

if (xhr.status >= 200 && xhr.status <= 300) {

resolve(JSON.parse(xhr.responseText))

} else {

reject(‘请求出错’)

}

}

}

xhr.send()  //发送hppt请求

})

return p

}

let url = ‘/data.json’

ajax(url).then(res => console.log(res))

.catch(reason => console.log(reason))

12. 手写节流防抖函数

防抖:

function debounce(fn, delay) {

if(typeof fn!==‘function’) {

throw new TypeError(‘fn不是函数’)

}

let timer; // 维护一个 timer

return function () {

var _this = this; // 取debounce执行作用域的this(原函数挂载到的对象)

var args = arguments;

if (timer) {

clearTimeout(timer);

}

timer = setTimeout(function () {

fn.apply(_this, args); // 用apply指向调用debounce的对象,相当于_this.fn(args);

}, delay);

};

}

input1.addEventListener(‘keyup’, debounce(() => {

console.log(input1.value)

}), 600)

节流:

function throttle(fn, delay) {

let timer;

return function () {

var _this = this;

var args = arguments;

if (timer) {

return;

}

timer = setTimeout(function () {

fn.apply(_this, args); // 这里args接收的是外边返回的函数的参数,不能用arguments

// fn.apply(_this, arguments); 需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受类数组对象。如果传入类数组对象,它们会抛出异常。

timer = null; // 在delay后执行完fn之后清空timer,此时timer为假,throttle触发可以进入计时器

}, delay)

}

}

div1.addEventListener(‘drag’, throttle((e) => {

console.log(e.offsetX, e.offsetY)

}, 100))

13. 手写Promise加载图片

function getData(url) {

return new Promise((resolve, reject) => {

$.ajax({

url,

success(data) {

resolve(data)

},

error(err) {

reject(err)

}

})

})

}

const url1 = ‘./data1.json’

const url2 = ‘./data2.json’

const url3 = ‘./data3.json’

getData(url1).then(data1 => {

console.log(data1)

return getData(url2)

}).then(data2 => {

console.log(data2)

return getData(url3)

}).then(data3 =>

console.log(data3)

).catch(err =>

console.error(err)

)

14. 函数实现一秒钟输出一个数

for(let i=0;i<=10;i++){   //用var打印的都是11

setTimeout(()=>{

console.log(i);

},1000*i)

}

15. 创建10个标签,点击的时候弹出来对应的序号?

var a

for(let i=0;i<10;i++){

a=document.createElement(‘a’)

a.innerHTML=i+‘

a.addEventListener(‘click’,function(e){

console.log(this)  //this为当前点击的

e.preventDefault()  //如果调用这个方法,默认事件行为将不再触发。

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
img

最后

如果你已经下定决心要转行做编程行业,在最开始的时候就要对自己的学习有一个基本的规划,还要对这个行业的技术需求有一个基本的了解。有一个已就业为目的的学习目标,然后为之努力,坚持到底。如果你有幸看到这篇文章,希望对你有所帮助,祝你转行成功。

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新

如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
[外链图片转存中…(img-DIL2quMh-1712374152022)]

最后

如果你已经下定决心要转行做编程行业,在最开始的时候就要对自己的学习有一个基本的规划,还要对这个行业的技术需求有一个基本的了解。有一个已就业为目的的学习目标,然后为之努力,坚持到底。如果你有幸看到这篇文章,希望对你有所帮助,祝你转行成功。

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!

AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值