无论是学习react还是vue,它们都是js的应用框架。剥去他们的壳子看到的始终是js,所以作为一个前端大厨必须要熟练掌握好js这个大勺,才能烧出一顿好菜
无论是自我提升还是应付面试以下这些手写功能是每一个前端程序员必须掌握的
每个Function对象都存在apply()、call()、bind() 方法,其作用都是可以在特定的作用域
中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。
1. 三者都可以改变this的指向,第一个参数都是this,如果指向是null或者undefined则指向window
2. apply的参数是数组,call是列表,而bind可以多次传入
3. apply和call是改变this的指向之后直接运行函数,而bind则是返回绑定之后的函数
/** * 手写apply */
window.name='gy' // 全局变量
let obj={
name:'ckx'
}
var func=function(b,c){
console.log(`this=`, this)
console.log(this.name,b,c)
return 1
}
func('24','hz') // gy 24 hz
func.apply(obj,['24','hz']) // ckx 24 hz
let newObj={
name:'xmx',
age:24
}
Function.prototype.myApply=function(base,args){
// 1. 如果指向是null 或者undefined 则指向window
base=base || window
// 2. 根据this是谁调用就指向谁的原理,将this指向的函数 赋值给base对象的一个属性
base.fn=this
// 3.执行函数,调用base.fn时,fn中的函数指向 base对象
let result=base.fn(...args)
// 4. 删除base的fn属性
delete base.fn
// 5. 返回result 结果
return result
}
func.myApply(newObj,['55','yw']) // xmx 55 yw
/** * 手写call */
window.name='gy' // 全局变量
let obj={
name:'ckx'
}
var func=function(b,c){
console.log(`this=`, this)
console.log(this.name,b,c)
return 1
}
func('24','hz') // gy 24 hz
func.call(obj,'24','hz') // ckx 24 hz
let newObj={
name:'xmx',
age:24
}
// call 和apply需要注意参数的格式即可
Function.prototype.myCall=function(base,...args){
// 1. 如果指向是null 或者undefined 则指向window
base=base || window
// 2. 根据this是谁调用就指向谁的原理,将this指向的函数 赋值给base对象的一个属性
base.fn=this
// 3.执行函数,调用base.fn时,fn中的函数指向 base对象
let result=base.fn(...args)
// 4. 删除base的fn属性
delete base.fn
// 5. 返回result 结果
return result
}
func.myCall(newObj,'55','yw') // xmx 55 yw
/** * 手写bind */
window.name = "gy"; // 全局变量
let obj = {
name: "ckx",
};
var func = function (b, c,d) {
console.log(`this=`, this);
console.log(this.name, b, c,d);
return 1;
};
func("24", "hz",26); // gy 24 hz 26
let funcRes = func.bind(obj, "24", "hz");
funcRes(24); // ckx 24 hz 24
let newObj = {
name: "xmx",
age: 24,
};
// 注意bind 返回的时绑定的函数以及可以多次传递参数
Function.prototype.myBind = function (base, ...args1) {
return (...args2) => {
// 1. 如果指向是null 或者undefined 则指向window
base = base || window;
// 2. 根据this是谁调用就指向谁的原理,将this指向的函数 赋值给base对象的一个属性
base.fn = this;
// 3.执行函数,调用base.fn时,fn中的函数指向 base对象
let result = base.fn(...args1,...args2);
// 4. 删除base的fn属性
delete base.fn;
// 5. 返回result 结果
return result;
};
};
let myfuncRes=func.myBind(newObj, "55", "yw")
myfuncRes(24) // xmx 55 yw 24
1. 创建了一个新对象
2. 将这个新对象与构造函数用原型链链接起来
3. 将构造函数的this指向新的对象,执行构造函数的代码赋值
4. 如果构造函数没有返回一个对象就返回新创建的对象否则返回构造函数返回的对象
/*** * 手写new关键字执行 */
function Person(name,age) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
};
let a = new Person('gy');
console.log(a);
console.log(a.getName());
const myNew = (Func, ...args) => {
let newObj = {};
newObj.__proto__=Func.prototype
let result=Func.apply(newObj,args)
return typeof result == Object ? result: newObj
};
let b = myNew(Person,'gy1')
console.log(b);
console.log(b.getName());
typeof 可以判断基本数据类型 但是null 返回的也是object 不能识别 引用数据类型
instanceof 可以准确的判断引用数据类型不可以判断 基本数据类型
instanceof是用于检测构造函数的prototype是否出现某个实例对象的原型链上
/*** 手写instanceof*/
let obj= { label:'gy' }
let arr= ['hello']
let result = obj instanceof Object
let result1 = arr instanceof Array
let result2 = arr instanceof Object
let result3 = obj instanceof Array
console.log('result=',result )
console.log('result1=',result1 )
console.log('result2=',result2 )
console.log('result3=',result3 )
const myInstanceof = (left,right)=>{
if(typeof left != 'object' || left == null ) return false
let proto= Object.getPrototypeOf(left)
while(true){
if(proto==null) return false
if(proto==right.prototype) return true
proto=Object.getPrototypeOf(proto)
}
}
const myResult= myInstanceof(obj,Object)
const myResult1= myInstanceof(arr,Array)
const myResult2= myInstanceof(arr,Object)
const myResult3= myInstanceof(obj,Array)
console.log('myRsult=',myResult )
console.log('myResult1=',myResult1 )
console.log('myResult2=',myResult2 )
console.log('myResult3=',myResult3 )
持续的触发某一事件,延迟n秒后执行回调,在未到n秒再次触发,会从新出发倒计时 持续的触发某一时间,延迟n秒后执行回调,在未达到n秒再次出发,不会重新计时
防抖
可能用于无法预知的用户主动行为,如用户输入内容去服务端动态搜索结果。用户打字的速度等是无法预知的,具有非规律性。
节流
可能用于一些非用户主动行为或者可预知的用户主动行为,如用户滑动商品橱窗时发送埋点请求、滑动固定的高度是已知的逻辑,具有规律性。
节流
和防抖
也是闭包的应用
/*** * 手写防抖 */
const debounce = (func, delay) => {
let timer = null;
return function (...args) {
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(() => {
func(args);
}, delay);
};
};
const getfn = (data) => {
console.log(data);
};
debounce(getfn, 2000)("gy");
/*** * 手写节流 * 这里只需要注意和防抖不同的时 不会清除定时器 */
const throttle = (func, delay) => {
let flag = false;
return function (...args) {
if (flag) return
flag=true
setTimeout(() => {
func(args);
flag=false
}, delay);
};
};
const getfn = (data) => {
console.log(data);
};
throttle(getfn, 2000)("gy");
AJAX 的全称为 Asynchronous JavaScript + XML, 最重要的要属 XHR(XMLHttpRequest)
XMLHttpRequest通过不刷新页面请求特定URL,获取数据。
XMLHttpRequest()
是一个构造函数XMLHttpRequest.onreadystatechange
状态码变化时触发事件(所有浏览器支持)XMLHttpRequest.readyState
请求的状态码XMLHttpRequest.status
响应状态码 返回标准的HTTP 状态码XMLHttpRequest.response 这个是整个响应实体
XMLHttpRequest.responseText 返回 DOMString
XMLHttpRequest.timeout 超时时间
XMLHttpRequest.upload 上传进度
open()
// method/url 是必须的
xhr.open(method, url, async, user, password); send()
// body 可选默认为null
// 可以是 Blob, BufferSource (en-US), FormData,
// URLSearchParams, 或者 USVString 对象.
XMLHttpRequest.send(body); setRequestHeader()
XMLHttpRequest.setRequestHeader(header, value);
// 例如
XMLHttpRequest.setRequestHeader ("content-type", "application/x-www-form-urlencoded" );
1. 构造一个请求 XMLHttpRequest
2. 初始化一个请求 open
3. 监听请求 onreadystatechange
4. 发送该请求 send
/*** 手写一个ajax*/
const myAjax =(url,methods,header,success,error)=>{
// 创建一个请求
let request=new XMLHttpRequest()
// 设置请求头
for (const key in header) {
request.setRequestHeader(key,header[key])
}
// 初始化请求
request.open(methods,url)
// 发送请求
request.send()
// 监听请求 onreadystatechange
request.onreadystatechange =function(){
if(request.readyState==4){
if(request.status==200){
success(request.response)
}else {
error()
}
}
}
}
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。