电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

詳解JavaScript中的鏈式調用

瀏覽:184日期:2023-10-07 10:17:50

鏈模式

鏈模式是一種鏈式調用的方式,準確來說不屬于通常定義的設計模式范疇,但鏈式調用是一種非常有用的代碼構建技巧。

描述

鏈式調用在JavaScript語言中很常見,如jQuery、Promise等,都是使用的鏈式調用,當我們在調用同一對象多次其屬性或方法的時候,我們需要多次書寫對象進行.或()操作,鏈式調用是一種簡化此過程的一種編碼方式,使代碼簡潔、易讀。鏈式調用通常有以下幾種實現方式,但是本質上相似,都是通過返回對象供之后進行調用。

this的作用域鏈,jQuery的實現方式,通常鏈式調用都是采用這種方式。 返回對象本身, 同this的區別就是顯示返回鏈式對象。 閉包返回對象的方式實現,這種方式與柯里化有相似之處。

var Person = function() {};Person.prototype.setAge = function(age){ this.age = age; return this;}Person.prototype.setWeight = function(weight){ this.weight = weight; return this;}Person.prototype.get = function(){ return `{age: ${this.age}, weight: ${this.weight}}`;}var person = new Person();var des = person.setAge(10).setWeight(30).get();console.log(des); // {age: 10, weight: 30}

var person = { age: null, weight: null, setAge: function(age){ this.age = age; return this; }, setWeight: function(weight){ this.weight = weight; return this; }, get: function(){ return `{age: ${this.age}, weight: ${this.weight}}`; }};var des = person.setAge(10).setWeight(30).get();console.log(des); // {age: 10, weight: 30}

function numsChain(num){ var nums = num; function chain(num){ nums = `${nums} -> ${num}`; return chain; } chain.get = () => nums; return chain;}var des = numsChain(1)(2)(3).get();console.log(des); // 1 -> 2 -> 3

可選鏈操作符

說到鏈式調用,就有必要說一下JavaScript的可選鏈操作符,屬于ES2020新特性運算符?.、??、??=,可選鏈操作符?.允許讀取位于連接對象鏈深處的屬性的值,而不必明確驗證鏈中的每個引用是否有效。?.操作符的功能類似于.鏈式操作符,不同之處在于在引用為空nullish即null或者undefined的情況下不會引起錯誤,該表達式短路返回值是undefined。與函數調用一起使用時,如果給定的函數不存在,則返回undefined。當嘗試訪問可能不存在的對象屬性時,可選鏈操作符將會使表達式更短更簡明。在探索一個對象的內容時,如果不能確定哪些屬性必定存在,可選鏈操作符也是很有幫助的。

語法

obj?.propobj?.[expr]arr?.[index]func?.(args)

示例

const obj = {a: {}};console.log(obj.a); // {}console.log(obj.a.b); // undefined// console.log(obj.a.b.c); // Uncaught TypeError: Cannot read property ’c’ of undefinedconsole.log(obj && obj.a); // {}console.log(obj && obj.a && obj.a.b && obj.a.b.c); // undefinedconsole.log(obj?.a?.b?.c); // undefinedconst test = void 0;const prop = 'a';console.log(test); // undefinedconsole.log(test?.a); // undefinedconsole.log(test?.[prop]); // undefinedconsole.log(test?.[0]); // undefinedconsole.log(test?.()); // undefined

jQuery中的鏈式調用

jQuery是一個高端而不失奢華的框架,其中有許多非常精彩的方法和邏輯,雖然現在非常流行于類似于Vue、React的MVVM模式的框架,但是jQuery的設計實在是棒,非常值得學習,在這里以最基礎的實例化jQuery為例探查一下jQuery如何通過this實現的鏈式調用。首先定義一個最基本的類,通過原型鏈去繼承方法。

function _jQuery(){}_jQuery.prototype = { constructor: _jQuery, length: 2, size: function(){ return this.length; }}var instance = new _jQuery();console.log(instance.size()); // 2// _jQuery.size() // Uncaught TypeError: _jQuery.size is not a function// _jQuery().size() / /Uncaught TypeError: Cannot read property ’size’ of undefined

通過定義一個類并且實現實例化之后,在實例之間可以共享原型上的方法,而直接通過_jQuery類直接去調用顯然是不行的,拋出的第一種異常是因為在_jQuery類上不存在靜態方法,第二種異常是因為_jQuery作為函數執行后未返回值,通過這里可以看出jQuery在通過$()方式調用的時候是返回了一個包含多個方法的對象的,而只是通過自己是訪問不到的,我們就借助另一個變量去訪問。

function _jQuery(){ return _fn;}var _fn = _jQuery.prototype = { constructor: _jQuery, length: 2, size: function(){ return this.length; }}console.log(_jQuery().size()); // 2

實際上jQuery為了減少變量的創建,直接將_fn看做了_jQuery的一個屬性。

function _jQuery(){ return _jQuery.fn;}_jQuery.fn = _jQuery.prototype = { constructor: _jQuery, length: 2, size: function(){ return this.length; }}console.log(_jQuery().size()); // 2

到這里確實能夠實現_jQuery()方式調用原型上的方法,但是在jQuery中$()的主要目標還是作為選擇器用來選擇元素,而現在返回的是一個_jQuery.fn對象,顯然是達不到要求的,為了能夠取得返回的元素,那就在原型上定義一個init方法去獲取元素,這里為了省事直接使用了document.querySelector,實際上jQuery的選擇器構建是很復雜的。

function _jQuery(selector){ return _jQuery.fn.init(selector);}_jQuery.fn = _jQuery.prototype = { constructor: _jQuery, init: function(selector){ return document.querySelector(selector); }, length: 3, size: function(){ return this.length; }}console.log(_jQuery('body')); // <body>...</body>

是似乎這樣又把鏈式調用的this給漏掉了,這里就需要利用this的指向了,因為在調用時this總是指向調用他的對象,所以我們在這里將選擇的元素掛載到this對象上即可。

function _jQuery(selector){ return _jQuery.fn.init(selector);}_jQuery.fn = _jQuery.prototype = { constructor: _jQuery, init: function(selector){ this[0] = document.querySelector(selector); this.length = 1; return this; }, length: 3, size: function(){ return this.length; }}var body = _jQuery('body');console.log(body); // {0: body, length: 1, constructor: ƒ, init: ƒ, size: ƒ}console.log(body.size()); // 1console.log(_jQuery.fn); // {0: body, length: 1, constructor: ƒ, init: ƒ, size: ƒ}

但是此時又出現了一個問題,我們的選擇器選擇的元素是直接掛載到了_jQuery.fn上,這樣的話由于原型是共享的,在之后的定義的選擇器就會將前邊定義的選擇器覆蓋掉,這樣顯然是不行的,于是我們使用new操作符新建一個對象。

function _jQuery(selector){ return new _jQuery.fn.init(selector);}_jQuery.fn = _jQuery.prototype = { constructor: _jQuery, init: function(selector){ this[0] = document.querySelector(selector); this.length = 1; return this; }, length: 3, size: function(){ return this.length; }}var body = _jQuery('body');console.log(body); // init {0: body, length: 1}// console.log(body.size()); // Uncaught TypeError: body.size is not a function

這樣又出現了問題,當我們使用new實例化_jQuery.fn.init時返回的this指向的是_jQuery.fn.init的實例,我們就不能進行鏈式調用了,jQuery用了一個非常巧妙的方法解決了這個問題,直接將_jQuery.fn.init的原型指向_jQuery.prototype,雖然會有循環引用的問題,但是相對來說這一點性能消耗并不算什么,由此我們完成了jQuery選擇器以及鏈式調用的實現。

function _jQuery(selector){ return new _jQuery.fn.init(selector);}_jQuery.fn = _jQuery.prototype = { constructor: _jQuery, init: function(selector){ this[0] = document.querySelector(selector); this.length = 1; return this; }, length: 3, size: function(){ return this.length; }}_jQuery.fn.init.prototype = _jQuery.fn;var body = _jQuery('body');console.log(body); // init {0: body, length: 1}console.log(body.size()); // 1console.log(_jQuery.fn.init.prototype.init.prototype.init.prototype === _jQuery.fn); // true

每日一題

https://github.com/WindrunnerMax/EveryDay

以上就是詳解JavaScript中的鏈式調用的詳細內容,更多關于JavaScript 鏈式調用的資料請關注好吧啦網其它相關文章!

標簽: JavaScript
相關文章:
主站蜘蛛池模板: 篷房|仓储篷房|铝合金篷房|体育篷房|篷房厂家-华烨建筑科技官网 知名电动蝶阀,电动球阀,气动蝶阀,气动球阀生产厂家|价格透明-【固菲阀门官网】 | 合肥地磅_合肥数控切割机_安徽地磅厂家_合肥世佳电工设备有限公司 | 模切之家-专注服务模切行业的B2B平台!| 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 防爆暖风机_防爆电暖器_防爆电暖风机_防爆电热油汀_南阳市中通智能科技集团有限公司 | 德国BOSCH电磁阀-德国HERION电磁阀-JOUCOMATIC电磁阀|乾拓百科 | 上海阳光泵业制造有限公司 -【官方网站】| 国际船舶网 - 船厂、船舶、造船、船舶设备、航运及海洋工程等相关行业综合信息平台 | 恒温恒湿箱(药品/保健品/食品/半导体/细菌)-兰贝石(北京)科技有限公司 | 千斤顶,液压千斤顶-力良企业,专业的液压千斤顶制造商,shliliang.com | 线粒体膜电位荧光探针-细胞膜-标记二抗-上海复申生物科技有限公司 | 锂电叉车,电动叉车_厂家-山东博峻智能科技有限公司 | 超声波成孔成槽质量检测仪-压浆机-桥梁预应力智能张拉设备-上海硕冠检测设备有限公司 | 合肥白癜风医院_[治疗白癜风]哪家好_合肥北大白癜风医院 | 阿米巴企业经营-阿米巴咨询管理-阿米巴企业培训-广东键锋企业管理咨询有限公司 | 六自由度平台_六自由度运动平台_三自由度摇摆台—南京全控科技 | 利浦顿蒸汽发生器厂家-电蒸汽发生器/燃气蒸汽发生器_湖北利浦顿热能科技有限公司官网 | 中图网(原中国图书网):网上书店,尾货特色书店,30万种特价书低至2折! | 减速机三参数组合探头|TSM803|壁挂式氧化锆分析仪探头-安徽鹏宸电气有限公司 | 申江储气罐厂家,储气罐批发价格,储气罐规格-上海申江压力容器有限公司(厂) | 桐城新闻网—桐城市融媒体中心主办| 三效蒸发器_多效蒸发器价格_四效三效蒸发器厂家-青岛康景辉 | 西安微信朋友圈广告投放_微信朋友圈推广_西安度娘网络科技有限公司 | 山东PE给水管厂家,山东双壁波纹管,山东钢带增强波纹管,山东PE穿线管,山东PE农田灌溉管,山东MPP电力保护套管-山东德诺塑业有限公司 | 地磅-电子地磅维修-电子吊秤-汽车衡-无人值守系统-公路治超-鹰牌衡器 | 昆山PCB加工_SMT贴片_PCB抄板_线路板焊接加工-昆山腾宸电子科技有限公司 | 厂房出租_厂房出售_产业园区招商_工业地产&nbsp;-&nbsp;中工招商网 | 地埋式垃圾站厂家【佳星环保】小区压缩垃圾中转站转运站 | 健康管理师报考条件,考试时间,报名入口—首页 | 蒸汽热收缩机_蒸汽发生器_塑封机_包膜机_封切收缩机_热收缩包装机_真空机_全自动打包机_捆扎机_封箱机-东莞市中堡智能科技有限公司 | 棉柔巾代加工_洗脸巾oem_一次性毛巾_浴巾生产厂家-杭州禾壹卫品科技有限公司 | 假肢-假肢价格-假肢厂家-河南假肢-郑州市力康假肢矫形器有限公司 | 风化石头制砂机_方解石制砂机_瓷砖石子制砂机_华盛铭厂家 | 液晶拼接屏厂家_拼接屏品牌_拼接屏价格_监控大屏—北京维康 | 纸塑分离机-纸塑分离清洗机设备-压力筛-碎浆机厂家金双联环保 | 火锅底料批发-串串香技术培训[川禾川调官网] | 新中天检测有限公司青岛分公司-山东|菏泽|济南|潍坊|泰安防雷检测验收 | 临时厕所租赁_玻璃钢厕所租赁_蹲式|坐式厕所出租-北京慧海通 | 收录网| 充气膜专家-气膜馆-PTFE膜结构-ETFE膜结构-商业街膜结构-奥克金鼎 | 首页|专注深圳注册公司,代理记账报税,注册商标代理,工商变更,企业400电话等企业一站式服务-慧用心 |