GG资源网

图解 Promise 实现原理(三):Promise 原型方法实现(JavaScript链式调用原理与实现方法讲解)

图解 Promise 实现原理(三):Promise 原型方法实现

作者:Morrain

转发链接:https://mp.weixin.qq.com/s/u8wuBwLpczkWCHx9TDt4Nw

前言

Promise 是异步编程的一种解决方案,它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。更多关于 Promise 的介绍请参考阮一峰老师的 ES6入门 之 Promise 对象。

很多同学在学习 Promise 时,知其然却不知其所以然,对其中的用法理解不了。本系列文章由浅入深逐步实现 Promise,并结合流程图、实例以及动画进行演示,达到深刻理解 Promise 用法的目的。

本系列文章由如下几个章节组成:

图解 Promise 实现原理(一):基础实现

图解 Promise 实现原理(二):Promise 链式调用

图解 Promise 实现原理(三):Promise 原型方法实现 (本篇)

图解 Promise 实现原理(四):Promise 静态方法实现

上一节中,实现了 Promise 的链式调用。链式调用是 Promise 的难点,更是重点。截至目前,Promise 的实现如下:

class Promise {
callbacks = [];
state = 'pending';//增加状态
value = null;//保存结果
constructor(fn) {
fn(this._resolve.bind(this));
}
then(onFulfilled) {
return new Promise(resolve => {
this._handle({
onFulfilled: onFulfilled || null,
resolve: resolve
});
});
}
_handle(callback) {
if (this.state === 'pending') {
this.callbacks.push(callback);
return;
}
//如果then中没有传递任何东西
if (!callback.onFulfilled) {
callback.resolve(this.value);
return;
}
var ret = callback.onFulfilled(this.value);
callback.resolve(ret);
}
_resolve(value) {
if (value && (typeof value === 'object' || typeof value === 'function')) {
var then = value.then;
if (typeof then === 'function') {
then.call(value, this._resolve.bind(this));
return;
}
}
this.state = 'fulfilled';//改变状态
this.value = value;//保存结果
this.callbacks.forEach(callback => this._handle(callback));
}
}

(滑动可查看)

本节主要介绍 Promise 原型方法的实现,包括 catch、finally 以及 rejected 状态等的实现。

【错误处理】

之前为了讲解原理,只是实现了 onFulfilled ,对于 Promise 来说,除了成功还有失败,在失败时,要标记 Promise 的状态为 rejected, 并执行注册的 onRejected。如下Demo所示:

/**
* 模拟异常异步请求
* @param {*} url
* @param {*} s
* @param {*} callback
*/
const mockAjax = (url, s, callback) => {
setTimeout(() => {
callback(url + '异步请求耗时' + s + '秒', '出错了!');
}, 1000 * s)
}

//demo reject
new Promise((resolve, reject) => {

mockAjax('getUserId', 1, function (result, error) {
if (error) {
reject(error)
} else {
resolve(result);
}
})

}).then(result => {
console.log(result);
}, error => {
console.log(error);
});

(滑动可查看)

有了之前处理 fulfilled 状态的经验,支持错误处理变得很容易,只需要在注册回调、处理状态变更上都要加入新的 reject 逻辑。

//完整的实现+reject
class Promise {
callbacks = [];
state = 'pending';//增加状态
value = null;//保存结果
constructor(fn) {
fn(this._resolve.bind(this), this._reject.bind(this));
}
then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
this._handle({
onFulfilled: onFulfilled || null,
onRejected: onRejected || null,
resolve: resolve,
reject: reject
});
});
}
_handle(callback) {
if (this.state === 'pending') {
this.callbacks.push(callback);
return;
}

let cb = this.state === 'fulfilled' ? callback.onFulfilled : callback.onRejected;

if (!cb) {//如果then中没有传递任何东西
cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;
cb(this.value);
return;
}

let ret = cb(this.value);
cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;
cb(ret);
}
_resolve(value) {

if (value && (typeof value === 'object' || typeof value === 'function')) {
var then = value.then;
if (typeof then === 'function') {
then.call(value, this._resolve.bind(this), this._reject.bind(this));
return;
}
}

this.state = 'fulfilled';//改变状态
this.value = value;//保存结果
this.callbacks.forEach(callback => this._handle(callback));
}
_reject(error) {
this.state = 'rejected';
this.value = error;
this.callbacks.forEach(callback => this._handle(callback));
}
}

(滑动可查看)

demo-reject的源码

地址:https://repl.it/@morrain2016/demo-reject

运行结果如下:

[Promse-1]:constructor
[Promse-1]:then
[Promse-2]:constructor
[Promse-1]:_handle state= pending
[Promse-1]:_handle callbacks= [ { onFulfilled: [Function],
onRejected: [Function],
resolve: [Function],
reject: [Function] } ]
=> Promise { callbacks: [], name: 'Promse-2', state: 'pending', value: null }
[Promse-1]:_reject
[Promse-1]:_reject value= 出错了!
[Promse-1]:_handle state= rejected
出错了!
[Promse-2]:_reject
[Promse-2]:_reject value= undefined

(滑动可查看)

【异常处理】

刚刚介绍了错误处理,是指在 Promise 的构造函数中发现的错误,并通过 reject 通知的。如果在执行 onFulfilled 或者 onRejected 时,出现了异常,该如何处理呢?对于这类异常,处理也很简单,可以使用 try-catch 捕获错误,然后将相应的 Promise 状态设置为 rejected 状态。改造_handle方法如下:

_handle(callback) {
if (this.state === 'pending') {
this.callbacks.push(callback);
return;
}

let cb = this.state === 'fulfilled' ? callback.onFulfilled : callback.onRejected;

if (!cb) {//如果then中没有传递任何东西
cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;
cb(this.value);
return;
}

let ret;

try {
ret = cb(this.value);
cb = this.state === 'fulfilled' ? callback.resolve : callback.reject;
} catch (error) {
ret = error;
cb = callback.reject
} finally {
cb(ret);
}

}

(滑动可查看)

demo-error的源码

地址:https://repl.it/@morrain2016/demo-error

不管是错误也好,异常也罢,最终都是通过 reject 实现的,可见最终对于错误以及异常的处理,都可以通过 then 中的 onRejected 来处理。所以单独增加一个 catch 方法,它是 .then(null, onRejected) 的别名。如下:

then(onFulfilled, onRejected) {
return new Promise((resolve, reject) => {
this._handle({
onFulfilled: onFulfilled || null,
onRejected: onRejected || null,
resolve: resolve,
reject: reject
});
});
}
catch(onError){
return this.then(null, onError);
}

(滑动可查看)

demo-catch的源码

地址:https://repl.it/@morrain2016/demo-catch

【Finally方法】

在实际应用的时候,我们很容易会碰到这样的场景,不管 Promise 最后的状态如何,都要执行某些操作(onDone)。例如服务器使用 Promise 处理请求,然后使用finally方法关掉服务器:

server.listen(port)
.then(function () {
// do something
})
.catch(error=>{
// handle error
})
.finally(server.stop);

(滑动可查看)

本质上,因为它是 then 的一种变形。上面的 demo 的效果等价于如下的代码:

server.listen(port)
.then(function () {
// do something
})
.catch(error=>{
// handle error
})
.then(server.stop, server.stop);

(滑动可查看)

通过上面的分析,finally看上去可以这么实现:

finally(onDone){
return this.then(onDone, onDone);
}

(滑动可查看)

但是由于 finally 方法的 onDone 不关心 Promise 的状态到底是 fulfilled 还是 rejected ,所以onDone 里的操作,应该是与状态无关的,并且不应该有任何参数。

如果使用 then 来实现就不符合 Promise 规范中关于《Why not .then(f, f)?》的说明 。一来 onDone 有参数,二来当 onDone 返回一个Promise时,会改变 finally 返回的Promise的值 状态 。

根据规范,finally实现如下:

catch(onError) {
return this.then(null, onError);
}
finally(onDone) {
if (typeof onDone !== 'function') return this.then();
let Promise = this.constructor;
return this.then(
value => Promise.resolve(onDone()).then(() => value),
reason => Promise.resolve(onDone()).then(() => { throw reason })
);
}

(滑动可查看)

demo-finally的源码

地址:https://repl.it/@morrain2016/demo-finally

new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 1000)
}).finally(() => {
console.log('onDone')
})

(滑动可查看)

对于上面的示例,执行结果如下:

[Promse-1]:constructor
[Promse-1]:finally
[Promse-1]:then
[Promse-2]:constructor
[Promse-1]:_handle state= pending
[Promse-1]:_handle callbacks= [ { onFulfilled: [Function],
onRejected: [Function],
resolve: [Function],
reject: [Function] } ]
=> Promise { callbacks: [], name: 'Promse-2', state: 'pending', value: null }
[Promse-1]:_resolve
[Promse-1]:_resolve value= success
[Promse-1]:_handle state= fulfilled
onDone
Promise::resolve
[Promse-3]:constructor
[Promse-3]:_resolve
[Promse-3]:_resolve value= undefined
[Promse-3]:then
[Promse-4]:constructor
[Promse-3]:_handle state= fulfilled
[Promse-4]:_resolve
[Promse-4]:_resolve value= success
[Promse-2]:_resolve
[Promse-2]:_resolve value= Promise {
callbacks: [],
name: 'Promse-4',
state: 'fulfilled',
value: 'success' }
[Promse-4]:then
[Promse-5]:constructor
[Promse-4]:_handle state= fulfilled
[Promse-2]:_resolve
[Promse-2]:_resolve value= success
[Promse-5]:_resolve
[Promse-5]:_resolve value= undefined

(滑动可查看)

finally 的实现看起来简单,实际理解还是比较困难,对于上面的实例,中间其实有5个 Promise实例生成。如下图所示:

原型方法就介绍这么多,下一节介绍两个静态方法

推荐JavaScript经典实例学习资料文章

《图解 Promise 实现原理(一):基础实现》

《图解 Promise 实现原理(二):Promise 链式调用》

《实践教你从零构建前端 Lint 工作流「干货」》

《高性能多级多选级联组件开发「JS篇」》

《深入浅出讲解Node.js CLI 工具最佳实战》

《延迟加载图像以提高Web网站性能的五种方法「实践」》

《比较 JavaScript 对象的四种方式「实践」》

《使用Service Worker让你的 Web 应用如虎添翼(上)「干货」》

《使用Service Worker让你的 Web 应用如虎添翼(中)「干货」》

《使用Service Worker让你的 Web 应用如虎添翼(下)「干货」》

《前端如何一次性处理10万条数据「进阶篇」》

《推荐三款正则可视化工具「JS篇」》

《如何让用户选择是否离开当前页面?「JS篇」》

《JavaScript开发人员更喜欢Deno的五大原因》

《仅用18行JavaScript实现一个倒数计时器》

《图文细说JavaScript 的运行机制》

《一个轻量级 JavaScript 全文搜索库,轻松实现站内离线搜索》

《推荐Web程序员常用的15个源代码编辑器》

《10个实用的JS技巧「值得收藏」》

《细品269个JavaScript小函数,让你少加班熬夜(一)「值得收藏」》

《细品269个JavaScript小函数,让你少加班熬夜(二)「值得收藏」》

《细品269个JavaScript小函数,让你少加班熬夜(三)「值得收藏」》

《细品269个JavaScript小函数,让你少加班熬夜(四)「值得收藏」》

《细品269个JavaScript小函数,让你少加班熬夜(五)「值得收藏」》

《细品269个JavaScript小函数,让你少加班熬夜(六)「值得收藏」》

《深入JavaScript教你内存泄漏如何防范》

《手把手教你7个有趣的JavaScript 项目-上「附源码」》

《手把手教你7个有趣的JavaScript 项目-下「附源码」》

《JavaScript 使用 mediaDevices API 访问摄像头自拍》

《手把手教你前端代码如何做错误上报「JS篇」》

《一文让你彻底搞懂移动前端和Web 前端区别在哪里》

《63个JavaScript 正则大礼包「值得收藏」》

《提高你的 JavaScript 技能10 个问答题》

《JavaScript图表库的5个首选》

《一文彻底搞懂JavaScript 中Object.freeze与Object.seal的用法》

《可视化的 JS:动态图演示 - 事件循环 Event Loop的过程》

《教你如何用动态规划和贪心算法实现前端瀑布流布局「实践」》

《可视化的 js:动态图演示 Promises & Async/Await 的过程》

《原生JS封装拖动验证滑块你会吗?「实践」》

《如何实现高性能的在线 PDF 预览》

《细说使用字体库加密数据-仿58同城》

《Node.js要完了吗?》

《Pug 3.0.0正式发布,不再支持 Node.js 6/8》

《纯JS手写轮播图(代码逻辑清晰,通俗易懂)》

《JavaScript 20 年 中文版之创立标准》

《值得收藏的前端常用60余种工具方法「JS篇」》

《箭头函数和常规函数之间的 5 个区别》

《通过发布/订阅的设计模式搞懂 Node.js 核心模块 Events》

《「前端篇」不再为正则烦恼》

《「速围」Node.js V14.3.0 发布支持顶级 Await 和 REPL 增强功能》

《深入细品浏览器原理「流程图」》

《JavaScript 已进入第三个时代,未来将何去何从?》

《前端上传前预览文件 image、text、json、video、audio「实践」》

《深入细品 EventLoop 和浏览器渲染、帧动画、空闲回调的关系》

《推荐13个有用的JavaScript数组技巧「值得收藏」》

《前端必备基础知识:window.location 详解》

《不要再依赖CommonJS了》

《犀牛书作者:最该忘记的JavaScript特性》

《36个工作中常用的JavaScript函数片段「值得收藏」》

《Node + H5 实现大文件分片上传、断点续传》

《一文了解文件上传全过程(1.8w字深度解析)「前端进阶必备」》

《【实践总结】关于小程序挣脱枷锁实现批量上传》

《手把手教你前端的各种文件上传攻略和大文件断点续传》

《字节跳动面试官:请你实现一个大文件上传和断点续传》

《谈谈前端关于文件上传下载那些事【实践】》

《手把手教你如何编写一个前端图片压缩、方向纠正、预览、上传插件》

《最全的 JavaScript 模块化方案和工具》

《「前端进阶」JS中的内存管理》

《JavaScript正则深入以及10个非常有意思的正则实战》

《前端面试者经常忽视的一道JavaScript 面试题》

《一行JS代码实现一个简单的模板字符串替换「实践」》

《JS代码是如何被压缩的「前端高级进阶」》

《前端开发规范:命名规范、html规范、css规范、js规范》

《【规范篇】前端团队代码规范最佳实践》

《100个原生JavaScript代码片段知识点详细汇总【实践】》

《关于前端174道 JavaScript知识点汇总(一)》

《关于前端174道 JavaScript知识点汇总(二)》

《关于前端174道 JavaScript知识点汇总(三)》

《几个非常有意思的javascript知识点总结【实践】》

《都2020年了,你还不会JavaScript 装饰器?》

《JavaScript实现图片合成下载》

《70个JavaScript知识点详细总结(上)【实践】》

《70个JavaScript知识点详细总结(下)【实践】》

《开源了一个 JavaScript 版敏感词过滤库》

《送你 43 道 JavaScript 面试题》

《3个很棒的小众JavaScript库,你值得拥有》

《手把手教你深入巩固JavaScript知识体系【思维导图】》

《推荐7个很棒的JavaScript产品步骤引导库》

《Echa哥教你彻底弄懂 JavaScript 执行机制》

《一个合格的中级前端工程师需要掌握的 28 个 JavaScript 技巧》

《深入解析高频项目中运用到的知识点汇总【JS篇】》

《JavaScript 工具函数大全【新】》

《从JavaScript中看设计模式(总结)》

《身份证号码的正则表达式及验证详解(JavaScript,Regex)》

《浏览器中实现JavaScript计时器的4种创新方式》

《Three.js 动效方案》

《手把手教你常用的59个JS类方法》

《127个常用的JS代码片段,每段代码花30秒就能看懂-【上】》

《深入浅出讲解 js 深拷贝 vs 浅拷贝》

《手把手教你JS开发H5游戏【消灭星星】》

《深入浅出讲解JS中this/apply/call/bind巧妙用法【实践】》

《手把手教你全方位解读JS中this真正含义【实践】》

《书到用时方恨少,一大波JS开发工具函数来了》

《干货满满!如何优雅简洁地实现时钟翻牌器(支持JS/Vue/React)》

《手把手教你JS 异步编程六种方案【实践】》

《让你减少加班的15条高效JS技巧知识点汇总【实践】》

《手把手教你JS开发H5游戏【黄金矿工】》

《手把手教你JS实现监控浏览器上下左右滚动》

《JS 经典实例知识点整理汇总【实践】》

《2.6万字JS干货分享,带你领略前端魅力【基础篇】》

《2.6万字JS干货分享,带你领略前端魅力【实践篇】》

《简单几步让你的 JS 写得更漂亮》

《恭喜你获得治疗JS this的详细药方》

《谈谈前端关于文件上传下载那些事【实践】》

《面试中教你绕过关于 JavaScript 作用域的 5 个坑》

《Jquery插件(常用的插件库)》

《【JS】如何防止重复发送ajax请求》

《JavaScript+Canvas实现自定义画板》

《Continuation 在 JS 中的应用「前端篇」》

作者:Morrain

转发链接:https://mp.weixin.qq.com/s/u8wuBwLpczkWCHx9TDt4Nw

JavaScript链式调用原理与实现方法讲解

本文实例讲述了JavaScript链式调用原理与实现方法。分享给大家供大家参考,具体如下:

1、什么是链式调用?

这个很容易理解,例如

$(\'text\').setStyle(\'color\', \'red\').show();

一般的函数调用和链式调用的区别:链式调用完方法后,return this返回当前调用方法的对象。

首先,我们先来看看一般函数的调用方式

(1)先创建一个简单的类

//创建一个bird类

function Bird(name) {

this.name=name;

this.run=function () {

document.write(name+\" \"+\"start run;\");

}

this.stopRun=function () {

document.write(name+\" \"+\"start run;\");

}

this.sing=function () {

document.write(name+\" \"+\"start sing;\");

}

this.stopSing=function () {

document.write(name+\" \"+\"start stopSing;\");

}

}

(2)使用方式:一般的调用方式

var bird=new Bird(\"测试\");

bird.run();

birdbird.sing();

bird.stopSing();

bird.stopRun();<br>

//结果为;测试 start run;测试 start sing;测试 start stopSing;测试 start run;

(3)总结,该种方式有一个弊端就是:多次重复使用一个对象变量

然后,我们再来看看将上述改成链式调用的格式

(1)在创建的简单类中加上return this,如下

//创建一个bird类

function Bird(name) {

this.name=name;

this.run=function () {

document.write(name+\" \"+\"start run;\");

return this;// return this返回当前调用方法的对象。

}

this.stopRun=function () {

document.write(name+\" \"+\"start run;\");

return this;

}

this.sing=function () {

document.write(name+\" \"+\"start sing;\");

return this;

}

this.stopSing=function () {

document.write(name+\" \"+\"start stopSing;\");

return this;

}

}

(2)使用链式调用(连缀的方式)

var bird=new Bird(\"测试\");
bird.run().sing().stopSing().stopRun();//结果为;测试 start run;测试 start sing;测试 start stopSing;测试 start run;

(3)总结此种方式的调用结果与一般的调用方式产生的结果一样,优点是:链式调用这种风格有助于简化代码的编写工作,让代码更加简洁、易读,同时也避免多次重复使用一个对象变量

2.模仿jquery的链式调用

第一步,定义一个含参数的空对象

(function(){

//下划线:表示私有变量的写法

function _$(els) { };//有参数的空对象

})()//程序启动的时候 里面的代码直接执行了

第二步,准备方法 在_$上定义一个onrReady方法

(function(){

//第一步,下划线:表示私有变量的写法

function _$(els) { };//有参数的空对象<br>

//第二步,准备方法 在_$上定义一个onrReady方法

_$.onrReady=function (fn) {

//按要求把对象(_$)注册到window对象上

//对外开放的接口

window.$=function () {

return new _$(arguments);//传递相应的方法调用参数 返回一可以使用function类原型上的方法的对象($(\"\")=_$(参数))

}

fn();

}

}

})()

第三步,为了类(Function)能扩展函数,我们定义一个它的静态函数

Function.prototype.method=function (name,fn) {//(函数名称,函数本身)

this.prototype[name]=fn;

return this;//链式调用关键

};//这个函数的意思:为function对象增加函数,会用链式调用,链式调用有两个参数name,和fn

第四步,扩展类的相应方法 链式的对象增加jquery库提供的操作函数

(function(){

//下划线:表示私有变量的写法

function _$(els) { };//有参数的空对象

//第二步,准备方法 在_$上定义一个onrReady方法

_$.onrReady=function (fn) {

//按要求把对象(_$)注册到window对象上

//对外开放的接口

window.$=function () {

return new _$(arguments);//传递相应的方法调用参数 返回一可以使用function类原型上的方法的对象($(\"\")=_$(参数))

}

fn();

}<br>   //第四步

//扩展类的相应方法 链式的对象增加jquery库提供的操作函数

_$.method(\"AddEvent\",function (type,fn) {//_$本身是一个function要继承原型链上的东西。

fn();

}).method(\"getEvent\",function (fn,e) {

fn();

})

})()

第五步,使用 ,需要调用_$.onReady方法才可以返回对象使用从function类继承而来的原型上的方法

(function () {

// (1)下划线:表示私有变量的写法

function _$(els) { };//有参数的空对象

//(2)准备方法 在_$上定义一个onrReady方法

// window.$=_$;

_$.onrReady=function (fn) {

//按要求把对象(_$)注册到window对象上  在任何地方都可以使用

//对外开放的接口

window.$=function () {//window 上先注册一个全局变量 与外界产生关系

return new _$(arguments);//传递相应的方法调用参数 返回一可以使用function类原型上的方法的对象($(\"\")=_$(参数))

}

fn();

}

//(4)扩展类的相应方法 链式的对象增加jquery库提供的操作函数

_$.method(\"AddEvent\",function (type,fn) {//_$本身是一个function要继承原型链上的东西。

fn();

}).method(\"getEvent\",function (fn,e) {

fn();

});

//第五步,开始使用 ,需要调用_$.onready方法才可以返回对象使用从function类继承而来的原型上的方法

_$.onrReady(function () {//$是绑定在Windows上的

$(\"\").AddEvent(\"click\",function () {

alert(\"click\")

})

})

})()

上述综合的代码为

//第三步,为了类(Function)能扩展函数,我们定义一个它的静态函数

Function.prototype.method=function (name,fn) {//(函数名称,函数本身)

this.prototype[name]=fn;

return this;//链式调用关键

};//这个函数的意思:为function对象增加函数,会用链式调用,链式调用有两个参数name,和fn

(function () {

// 第一步,下划线:表示私有变量的写法

function _$(els) { };//有参数的空对象

//第二步,准备方法 在_$上定义一个onrReady方法

// window.$=_$;

_$.onrReady=function (fn) {

//按要求把对象(_$)注册到window对象上

//对外开放的接口

window.$=function () {

return new _$(arguments);//传递相应的方法调用参数 返回一可以使用function类原型上的方法的对象($(\"\")=_$(参数))

}

fn();

}

//第四步,扩展类的相应方法 链式的对象增加jquery库提供的操作函数

_$.method(\"AddEvent\",function (type,fn) {//_$本身是一个function要继承原型链上的东西,所以可以使用method方法

fn();

}).method(\"getEvent\",function (fn,e) {

fn();

});

//第五步,开始使用,需要调用_$.onready方法才可以返回对象使用从function类继承而来的原型上的方法

_$.onrReady(function () {//$是绑定在Windows上的

$(\"\").AddEvent(\"click\",function () {

alert(\"click\")

})

})

})()

上述是将$绑定到window上的操作,如果我们想将$绑定到一个指定对象上我们可以这通过改变上述的第二步和第五步如下,

/**

* Created by 与你在巅峰相会 on 2017/10/12.

*/

//第三步,为了类(Function)能扩展函数,我们定义一个它的静态函数

Function.prototype.method=function (name,fn) {//(函数名称,函数本身)

this.prototype[name]=fn;

return this;//链式调用关键

};//这个函数的意思:为function对象增加函数,会用链式调用,链式调用有两个参数name,和fn

(function () {

// 第一步,下划线:表示私有变量的写法

function _$(els) { };//有参数的空对象

//第二步,准备方法 在_$上定义一个onrReady方法

_$.onReady=function (obj,fn) {//obj传进来的对象

if(obj){

//按要求把对象(_$)注册到window对象上

//对外开放的接口

obj.$=function () {

return new _$(arguments);//传递相应的方法调用参数 返回一可以使用function类原型上的方法的对象($(\"\")=_$(参数))

}

}else {

//按要求把对象(_$)注册到window对象上

//对外开放的接口

window.$=function () {

return new _$(arguments);//传递相应的方法调用参数 返回一可以使用function类原型上的方法的对象($(\"\")=_$(参数))

}

}

fn();

}

//第四步,扩展类的相应方法 链式的对象增加jquery库提供的操作函数

_$.method(\"AddEvent\",function (type,fn) {//_$本身是一个function要继承原型链上的东西,可以直接使用method方法

fn();

}).method(\"getEvent\",function (fn,e) {

fn();

});

//第五步,开始使用,需要调用_$.onready方法才可以返回对象使用从function类继承而来的原型上的方法

var com={};

_$.onReady(com,function () {//$是绑定在Windows上的

com.$(\"\").AddEvent(\"click\",function () {

alert(\"click\")

})

})

})()

自己画一个图简单理解一下上面的过程及思路:

JavaScript链式调用原理与实现方法讲解 (https://www.wpmee.com/) javascript教程 第1张

由于网站搬家,部分链接失效,如无法下载,请联系站长!谢谢支持!
1. 带 [亲测] 说明源码已经被站长亲测过!
2. 下载后的源码请在24小时内删除,仅供学习用途!
3. 分享目的仅供大家学习和交流,请不要用于商业用途!
4. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!
5. 本站所有资源来源于站长上传和网络,如有侵权请邮件联系站长!
6. 没带 [亲测] 代表站长时间紧促,站长会保持每天更新 [亲测] 源码 !
7. 盗版ripro用户购买ripro美化无担保,若设置不成功/不生效我们不支持退款!
8. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
9. 如果你也有好源码或者教程,可以到审核区发布,分享有金币奖励和额外收入!
10.如果您购买了某个产品,而我们还没来得及更新,请联系站长或留言催更,谢谢理解 !
GG资源网 » 图解 Promise 实现原理(三):Promise 原型方法实现(JavaScript链式调用原理与实现方法讲解)

发表回复

CAPTCHAis initialing...