通過各種手寫,可以深入理解js的ES6的語法對(duì)應(yīng)的作用以及運(yùn)作規(guī)律劲室。
一伦仍、手寫new
1 創(chuàng)建一個(gè)新對(duì)象。
2 將構(gòu)造函數(shù)的作用域賦給新對(duì)象(因此this就指向了這個(gè)對(duì)象)很洋。
3 執(zhí)行構(gòu)造函數(shù)中的代碼(為這個(gè)新對(duì)象添加屬性)充蓝。
4 返回新對(duì)象。
function myNew(){
let obj={}; //創(chuàng)建一個(gè)新對(duì)象
let Constructor=[].shift.call(arguments); //獲取第一個(gè)參數(shù)喉磁,為構(gòu)造函數(shù),同時(shí)這個(gè)操作也會(huì)彈出arguments類數(shù)組的第一個(gè)參數(shù)
obj.__proto__=Constructor.prototype; // 將這個(gè)新對(duì)象掛上構(gòu)造函數(shù)的原型鏈
let res=Constructor.call(obj,...arguments); //this指向obj
return typeof res==="object"?res:obj; //判斷是不是為對(duì)象谓苟,不是,則返空對(duì)象协怒。
}
或者
function myNew(Obj,...args){
let obj = Object.create(Obj.prototype);//使用指定的原型對(duì)象及其屬性去創(chuàng)建一個(gè)新的對(duì)象
Obj.call(obj,...args); // 綁定 this 到obj, 設(shè)置 obj 的屬性
return obj; // 返回實(shí)例
}
二涝焙、手寫promise,promise.all孕暇,promise.race
1. promise簡(jiǎn)易版
詳細(xì)版
function myPromise(exector){
let self=this;
this.status="pending";
// 這里我們將value 成功時(shí)候的值 reason失敗時(shí)候的值放入屬性中
this.value=undefined;
this.reason=undefined;
// 存儲(chǔ)then中成功的回調(diào)函數(shù)
this.onResolvedCallbacks=[];
// 存儲(chǔ)then中失敗的回調(diào)函數(shù)
this.onRejectedCallbacks=[];
//執(zhí)行成功時(shí)仑撞,
function resolve(value){
if(self.status==="pending"){
self.value=value;
self.status="resolved";
self.onResolvedCallbacks.forEach(fn=>fn());
}
}
//執(zhí)行失敗
function reject(reason){
if(self.status==="pending"){
self.reason=reason;
self.status="rejected";
self.onRejectedCallbacks.forEach(fn=>fn());
}
}
// 這里對(duì)異常進(jìn)行處理
try {
exector(resolve, reject);
} catch(e) {
reject(e)
}
}
//then改造
myPromise.prototype.then=function(onFullfilled,onRejected){
let self=this;
if(this.status==="resoved")
onFullfilled(self.value);
if(this.status==="rejected")
onRejected(self.reason);
if(this.status==="pending"){
// 保存回調(diào)函數(shù)
this.onResolvedCallbacks.push(()=>{
onFullfilled(self.value);
})
this.onRejectedCallbacks.push(()=>{
onRejected(self.reason);
})
}
return this;
}
省略版
class MyPromise {
succeed = null
fail = null
state = 'pending'
constructor(fn) {
fn(this.resolve.bind(this), this.reject.bind(this))
}
resolve(result) {
setTimeout(() => {
this.state = 'fulfilled'
this.succeed(result)
})
}
reject(reason) {
setTimeout(() => {
this.state = 'rejected'
this.fail(reason)
})
}
then(succeed, fail) {
this.succeed = succeed
this.fail = fail
}
}
2. promise.all
myPromise.all=function(parr){
return new myPromise(function(resolve,reject){
let result=[];
let count=0;
for(let i=0;i<parr.length;i++){
parr[i].then(function(data){
result[i]=data;
count++;
if(count===parr.length) resolve(result);
},function(error){
reject(error);
})
}
})
}
3. promise.race
myPromise.race=function(parr){
return new myPromise((resolve,reject)=>{
for(let i=0;i<parr.length;i++){
parr[i].then(data=>{resolve(data)},error=>{reject(error)})
}
}
}
4. 實(shí)現(xiàn)catch方法
Promise.prototype.catch=(onRejected)=>{
return this.then(null,onRejected);
})
三、promise封裝JSONP
function jsonp(url){
return new Promise((resolve,reject)=>{
const random="xiaokaiJSONCallbackName"+Math.random();
window[random]=(data)=>{
resolve(data);
}
const script=document.createElement("script");
script.src=`${url}?callback=${random}`;
script.onload=()=> {
script.remove();
}
script.onerror=()=>{
reject();
}
document.body.appendChild(script);
})
}
//然后在需要傳的js文件里寫 window['{{xxx}}']('{{data}}')芭商,后臺(tái)讀取后根據(jù)查詢參數(shù)和數(shù)據(jù)寫新的數(shù)據(jù)于js派草。
四、手寫promisify函數(shù)
問題:
對(duì)于一個(gè)回調(diào)函數(shù)f(a,b,c,(err,res)=>{})铛楣,把他promisify化
栗子:const f1=promisify(f)
f1(a,b,c).then().catch()
function promisify(fn){
return function(...args){
return new promise((resolve,reject)=>{
fn(...args,(err,res)=>{
err?reject(err):resolve(res);
});
})
}
}
五近迁、手寫curry化(喵的被虐了)
function curry(fn){
let len=fn.length;
let args=[];
return function curryFn(...partArgs){
args=args.concat(partArgs);
if(args.length<len){
return curryFn;
}else if(args.length>len{
throw new Error("參數(shù)有問題!")
}else{
return fn(...args);
}
}
}
六簸州、簡(jiǎn)易實(shí)現(xiàn)鏈?zhǔn)秸{(diào)用(喵的被虐了)
function createObj(){};
createObj.prototype={
work(){return this};
sleep(time){ setTimeOut(()=>{return this},time)};
lunch(){return this};
}