亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解JavaScript中的鏈?zhǔn)秸{(diào)用

 更新時(shí)間:2020年11月27日 09:03:33   作者:WindrunnerMax  
這篇文章主要介紹了JavaScript中的鏈?zhǔn)秸{(diào)用的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)JavaScript,感興趣的朋友可以了解下

鏈模式

鏈模式是一種鏈?zhǔn)秸{(diào)用的方式,準(zhǔn)確來(lái)說(shuō)不屬于通常定義的設(shè)計(jì)模式范疇,但鏈?zhǔn)秸{(diào)用是一種非常有用的代碼構(gòu)建技巧。

描述

鏈?zhǔn)秸{(diào)用在JavaScript語(yǔ)言中很常見(jiàn),如jQuery、Promise等,都是使用的鏈?zhǔn)秸{(diào)用,當(dāng)我們?cè)谡{(diào)用同一對(duì)象多次其屬性或方法的時(shí)候,我們需要多次書(shū)寫(xiě)對(duì)象進(jìn)行.或()操作,鏈?zhǔn)秸{(diào)用是一種簡(jiǎn)化此過(guò)程的一種編碼方式,使代碼簡(jiǎn)潔、易讀。
鏈?zhǔn)秸{(diào)用通常有以下幾種實(shí)現(xiàn)方式,但是本質(zhì)上相似,都是通過(guò)返回對(duì)象供之后進(jìn)行調(diào)用。

  • this的作用域鏈,jQuery的實(shí)現(xiàn)方式,通常鏈?zhǔn)秸{(diào)用都是采用這種方式。
  • 返回對(duì)象本身, 同this的區(qū)別就是顯示返回鏈?zhǔn)綄?duì)象。
  • 閉包返回對(duì)象的方式實(shí)現(xiàn),這種方式與柯里化有相似之處。
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

可選鏈操作符

說(shuō)到鏈?zhǔn)秸{(diào)用,就有必要說(shuō)一下JavaScript的可選鏈操作符,屬于ES2020新特性運(yùn)算符?.、??、??=,可選鏈操作符?.允許讀取位于連接對(duì)象鏈深處的屬性的值,而不必明確驗(yàn)證鏈中的每個(gè)引用是否有效。?.操作符的功能類(lèi)似于.鏈?zhǔn)讲僮鞣?,不同之處在于在引用為空nullish即null或者undefined的情況下不會(huì)引起錯(cuò)誤,該表達(dá)式短路返回值是undefined。與函數(shù)調(diào)用一起使用時(shí),如果給定的函數(shù)不存在,則返回undefined。當(dāng)嘗試訪(fǎng)問(wèn)可能不存在的對(duì)象屬性時(shí),可選鏈操作符將會(huì)使表達(dá)式更短更簡(jiǎn)明。在探索一個(gè)對(duì)象的內(nèi)容時(shí),如果不能確定哪些屬性必定存在,可選鏈操作符也是很有幫助的。

語(yǔ)法

obj?.prop
obj?.[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 undefined
console.log(obj && obj.a); // {}
console.log(obj && obj.a && obj.a.b && obj.a.b.c); // undefined
console.log(obj?.a?.b?.c); // undefined

const test = void 0;
const prop = "a";
console.log(test); // undefined
console.log(test?.a); // undefined
console.log(test?.[prop]); // undefined
console.log(test?.[0]); // undefined
console.log(test?.()); // undefined

jQuery中的鏈?zhǔn)秸{(diào)用

jQuery是一個(gè)高端而不失奢華的框架,其中有許多非常精彩的方法和邏輯,雖然現(xiàn)在非常流行于類(lèi)似于Vue、React的MVVM模式的框架,但是jQuery的設(shè)計(jì)實(shí)在是棒,非常值得學(xué)習(xí),在這里以最基礎(chǔ)的實(shí)例化jQuery為例探查一下jQuery如何通過(guò)this實(shí)現(xiàn)的鏈?zhǔn)秸{(diào)用。
首先定義一個(gè)最基本的類(lèi),通過(guò)原型鏈去繼承方法。

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

通過(guò)定義一個(gè)類(lèi)并且實(shí)現(xiàn)實(shí)例化之后,在實(shí)例之間可以共享原型上的方法,而直接通過(guò)_jQuery類(lèi)直接去調(diào)用顯然是不行的,拋出的第一種異常是因?yàn)樵赺jQuery類(lèi)上不存在靜態(tài)方法,第二種異常是因?yàn)開(kāi)jQuery作為函數(shù)執(zhí)行后未返回值,通過(guò)這里可以看出jQuery在通過(guò)$()方式調(diào)用的時(shí)候是返回了一個(gè)包含多個(gè)方法的對(duì)象的,而只是通過(guò)自己是訪(fǎng)問(wèn)不到的,我們就借助另一個(gè)變量去訪(fǎng)問(wèn)。

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

實(shí)際上jQuery為了減少變量的創(chuàng)建,直接將_fn看做了_jQuery的一個(gè)屬性。

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

到這里確實(shí)能夠?qū)崿F(xiàn)_jQuery()方式調(diào)用原型上的方法,但是在jQuery中$()的主要目標(biāo)還是作為選擇器用來(lái)選擇元素,而現(xiàn)在返回的是一個(gè)_jQuery.fn對(duì)象,顯然是達(dá)不到要求的,為了能夠取得返回的元素,那就在原型上定義一個(gè)init方法去獲取元素,這里為了省事直接使用了document.querySelector,實(shí)際上jQuery的選擇器構(gòu)建是很復(fù)雜的。

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>

是似乎這樣又把鏈?zhǔn)秸{(diào)用的this給漏掉了,這里就需要利用this的指向了,因?yàn)樵谡{(diào)用時(shí)this總是指向調(diào)用他的對(duì)象,所以我們?cè)谶@里將選擇的元素掛載到this對(duì)象上即可。

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()); // 1
console.log(_jQuery.fn); // {0: body, length: 1, constructor: ƒ, init: ƒ, size: ƒ}

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

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

這樣又出現(xiàn)了問(wèn)題,當(dāng)我們使用new實(shí)例化_jQuery.fn.init時(shí)返回的this指向的是_jQuery.fn.init的實(shí)例,我們就不能進(jìn)行鏈?zhǔn)秸{(diào)用了,jQuery用了一個(gè)非常巧妙的方法解決了這個(gè)問(wèn)題,直接將_jQuery.fn.init的原型指向_jQuery.prototype,雖然會(huì)有循環(huán)引用的問(wèn)題,但是相對(duì)來(lái)說(shuō)這一點(diǎn)性能消耗并不算什么,由此我們完成了jQuery選擇器以及鏈?zhǔn)秸{(diào)用的實(shí)現(xiàn)。

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()); // 1
console.log(_jQuery.fn.init.prototype.init.prototype.init.prototype === _jQuery.fn); // true

每日一題

https://github.com/WindrunnerMax/EveryDay

以上就是詳解JavaScript中的鏈?zhǔn)秸{(diào)用的詳細(xì)內(nèi)容,更多關(guān)于JavaScript 鏈?zhǔn)秸{(diào)用的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

最新評(píng)論