「这是我参与11月更文挑战的第3天,活动详情查看:2021最后一次更文挑战」。
手写代码示例
实现Object.create
Object.create:创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。
const mycreate = function(obj){
function F(){}
F.prototype=obj
return new F()
}
复制代码
原生实现jsonp
思路:<script>
标签可以跨域引入资源,通过指定callback回调函数得到数据。
//原理:<script>标签可以跨域引入资源
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = 'http://localhost:8080/users?username=xbc&callback='+callbackName;
document.body.appendChild(script);
// 回调执行函数
function callbackName(res) {
data = JSON.stringify(res)
console.log(data);
}
ps:注意指定函数名callbackName
复制代码
原生实现http请求
思路:通过new XMLHttpRequest()实现,捕获onreadystatechange并做对应的处理。
重要:XMLHttpRequest
const getJSON = function (url) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// xhr.setRequestHeader("Content-Type", "application/json");
xhr.open("GET", url);
xhr.onreadystatechange = function () {
if (xhr.readyState !== 4) return;
// 状态码为200至300之间或304都表示这一请求已经成功
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
resolve(xhr.responseText);
} else {
reject(new Error(xhr.responseText));
}
};
xhr.send(); //xhr.send(data) POST
});
};
// 兼容IE5和IE6可选
// function createXHR() {
// if (window.XMLHttpRequest) {
// return new XMLHttpRequest();
// } else {
// return new ActiveXObject('Microsoft.XMLHttp');
// }
// }
ps:主要属性 on ready state change
复制代码
数组排序
1. 函数-sort
const arr=[1,30,4,21,99]
arr.sort((a,b)=>{
return a - b;
})
//[1, 4, 21, 30, 99]
//ps: b - a; 大到小
//sort函数还可以根据指定属性值排序json数组
例:
arr.sort((a,b)=>{
return a.key - b.key
})
复制代码
2. 冒泡
思路:两两对比,反序则交换
//思路:两两对比,反序则交换
const arr=[1,20,4,21,99,88]
for(let i=0;i<arr.length-1;i++){
for(let n=0;n<arr.length-i-1;n++){
if(arr[n]>arr[n+1]){
let x=arr[n]
arr[n]=arr[n+1]
arr[n+1]=x
}
}
}
//[1,4,21,30,88,99]
//ps:arr[n]<arr[n+1];大到小
复制代码
3. 快排
思路:先从数组中找一个基准数,把数组拆解成大于基准数区和小于基准数区两部分,再对左右区间重复第二步,直到各区间只有一个数
//思路:先从数组中找一个基准数,把数组拆解成大于基准数区和小于基准数区两部分,再对左右区间重复第二步,直到各区间只有一个数
const arr=[1,20,3,21,99,88]
function quick(arr){
if(arr.length<=1) return arr;
let left=[], right=[], mid=arr.splice(0,1)[0]
for(let i=0;i<arr.length;i++){
if(arr[i]<mid){
left.push(arr[i])
}else{
right.push(arr[i])
}
}
return quick(left).concat(mid,quick(right))
}
// [1, 3, 20, 21, 88, 99]
//ps:arr[i]>mid;大到小
复制代码
数组合并&去重
//2021年了,扩展运算符。(当然方法很多map、key值去重、过滤器等)
const a=[1,2,3]
const b=[4,5,6]
const c=[...new Set([...a,...b])];
//[a,b,c,d,e,f]
复制代码
非空判断不包含0
let value=0
if((value??'') !== ''){
console.log('非空')
}
ps:这里对两个假值('' 或 0)做处理,当value为0时,结果就是(0!=='')得到true。
当value为''时,结果就是(''!=='')得到false。
复制代码
重点:空值合并操作符( ??
)是一个逻辑操作符,当左侧的操作数为 null
或者 undefined
时,返回其右侧操作数,否则返回左侧操作数。(另外??运算符和其他逻辑运算符之间的运算顺序目前没有明确说明,所以用())
拷贝
let obj={
name:'张三',
age:'18',
grades:[88,99,58,68]
}
//浅拷贝
let obj2={...obj}
//深拷贝
let obj2=JSON.parse(JSON.stringify(obj));
//ps:根据实际场景来使用,复杂场景可以使用工具库,比如lodash
复制代码
原型链继承
思路:
1、让子类能访问父类的方法
2、对constructor处理,让子类的constructor属性指向自身(constructor属性是对函数本身的引用)
// 父类方法(Superclass)
function Superclass() {
this.supName = "我是父类"
}
// 父类添加原型方法
Superclass.prototype.showSupName = function () {
console.log(this.supName)
}
//子类(Subclass)
function Subclass() {
this.subName = "我是子类"
}
/**
* 1 让子类能访问父类的方法
* 2 让子类的constructor属性指向自身(constructor属性是对函数本身的引用)
**/
Subclass.prototype = new Superclass();
Subclass.prototype.constructor = Subclass
// 子类添加原型方法
Subclass.prototype.showSubName = function () {
console.log(this.subName)
}
// 子类调用父类方法
var sub = new Subclass();
sub.showSupName();
/*ps:如果想要继承父类的属性可调用父类的function.call(thisArg, arg1, arg2, ...);方法给父类提供子类的this值来实现*/
复制代码
Proxy使用,监听数据变化更新dom
思路:通过创建代理对象,对handler.set()
设置属性值劫持,然后更新innerHTML
<div id="name"></div>
---------------------------华丽的分割线----------------------------
let data = {
name: '唐三'
}
const handler = {
set: function (obj, prop, val) {
console.log(obj[prop], '监听set改变', obj, prop, val)
obj[prop] = val;
observer();
}
};
const p = new Proxy(data, handler);
document.getElementById('name').innerHTML = p.name
//打怪升级
setTimeout(() => {
p.name = '海神'
}, 2000);
function observer() {
document.getElementById('name').innerHTML = p.name
}
ps:**Proxy** 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)
复制代码
note:handler
对象如果没有定义某个捕捉器,那么就会保留源对象的默认行为,反之。
Object.defineProperty
也可以实现但有很多弊端,有好的咱就尽量用好的,至少我是这样的。
结尾
算是一份回顾基础的笔记吧,没有深究,没必要吧!主要还是记录实现原理,持续更新。