يمكن أن تساعد قراءة الكود المصدري لأطر العمل المعروفة المبرمج على تحسين مهاراته المهنية. مؤلف المقال ، الذي ننشر ترجمته اليوم ، قام مؤخرًا بتحليل رمز vue2.x. وجد في هذا الرمز بعض أفكار جافا سكريبت المثيرة للاهتمام التي قرر مشاركتها مع الجميع.![](https://habrastorage.org/webt/rj/id/7b/rjid7bottz6bd-zfoz7cx83ljgy.jpeg)
1. تحديد نوع أي كائن بالضبط
وكما نعلم جميعا، في جافا سكريبت هناك ستة أنواع البيانات البدائية ( Boolean
، Number
، String
، Null
، Undefined
، Symbol
)، ونوع واحد وجوه - Object
. هل تعرف كيف تميز بين أنواع قيم الكائنات المختلفة؟ يمكن أن يكون الكائن صفيفًا أو دالة ، يمكن أن يكون مجموعة من القيم Map
أو أي شيء آخر. ما الذي يجب القيام به لمعرفة نوع الكائن بالضبط؟قبل البحث عن إجابة لهذا السؤال ، دعونا نفكر في الفرق بين Object.prototype.toString.call(arg)
و String(arg)
.يهدف استخدام هذه التعبيرات إلى تحويل المعلمة التي تم تمريرها إليها إلى سلسلة. لكنهم يعملون بشكل مختلف.عند الاتصال ، String(arg)
سيحاول النظام الاتصال arg.toString()
أو arg.valueOf()
. ونتيجة لذلك ، إذا كان في arg
أو في النموذج الأوليarg
وهذه الطرق تكون الكتابة، والمكالمات Object.prototype.toString.call(arg)
و String(arg)
سوف يعطي نتائج مختلفة.تأمل في مثال.const _toString = Object.prototype.toString
var obj = {}
obj.toString()
_toString.call(obj)
سنقوم بتنفيذ هذا الرمز في وحدة تحكم أداة مطور المتصفح.في هذه المكالمات حالة obj.toString()
و Object.prototype.toString.call(obj)
تؤدي إلى نفس النتائج.هنا مثال آخر.const _toString = Object.prototype.toString
var obj = {}
obj.toString = () => '111'
obj.toString()
_toString.call(obj)
/hello/.toString()
_toString.call(/hello/)
دعونا تنفيذ التعليمات البرمجية في وحدة التحكم.الآن ، استدعاء طريقة الكائن .toString()
واستخدام البناء Object.prototype.toString.call(obj)
يعطي نتائج مختلفة.فيما يلي القواعد التي تصف سلوك طريقة في معيار ECMAScript Object.prototype.toString()
.وصف طريقة Object.prototype.toString () في معيار ECMAScriptبالنظر إلى الوثائق ، يمكننا أن نستنتج أنه عندObject.prototype.toString()
طلب كائنات مختلفة ، سيتم إرجاع نتائج مختلفة.استكشف هذه الفكرة في وحدة التحكم.بالإضافة إلى ذلك ، Object.prototype.toString()
يتم دائمًا تقديم القيمة التي تم إرجاعها بالتنسيق التالي:‘[object ’ + ‘tag’ +‘] ’
إذا كنا بحاجة إلى استخراج جزء فقط من هذا البناء tag
، فيمكننا الوصول إلى هذا الجزء عن طريق إزالة الأحرف غير الضرورية من بداية السطر ونهايته باستخدام تعبير أو طريقة عادية String.prototype.slice()
.function toRawType (value) {
const _toString = Object.prototype.toString
return _toString.call(value).slice(8, -1)
}
toRawType(null)
toRawType(/sdfsd/)
استكشف هذه الميزة في وحدة التحكم.كما ترى ، باستخدام الوظيفة أعلاه ، يمكنك معرفة النوع الدقيق لمتغير الكائن.→ هنا ، في مستودع Vue ، يمكنك العثور على رمز وظيفة مشابهة.2. التخزين المؤقت لنتائج الوظيفة
افترض أن هناك دالة مشابهة لما يلي تؤدي إلى عمليات حسابية طويلة:function computed(str) {
console.log('2000s have passed')
return 'a result'
}
من خلال إنشاء هذه الوظيفة ، ننوي تخزين النتائج التي تم إرجاعها إليها. عندما يتم استدعاء هذه الوظيفة في المرة القادمة ، بتمريرها نفس المعلمات كما كانت من قبل ، لن يتم تنفيذ رمز الوظيفة "الثقيلة". بدلاً من ذلك ، سيتم إرجاع النتيجة المخبأة ، دون أي وقت إضافي. كيف افعلها؟يمكنك ، على سبيل المثال ، كتابة دالة مجمعة لوظيفة موضوعية. يمكن إعطاء هذه الوظيفة اسمًا cached
. تقبل هذه الدالة ، كوسيطة ، دالة الهدف ، وتعيد وظيفة جديدة مجهزة بقدرات التخزين المؤقت. في الوظيفة ، cached
يمكنك تخزين نتائج المكالمات السابقة إلى الوظيفة المستهدفة في ذاكرة التخزين المؤقت باستخدام الكيان Object
أو Map
. إليك رمز هذه الوظيفة:function cached(fn){
const cache = Object.create(null);
return function cachedFn (str) {
if ( !cache[str] ) {
let result = fn(str);
cache[str] = result;
}
return cache[str]
}
}
هنا مثال على استخدام الوظيفة أعلاه.→ هنا هو رمز وظيفة مماثلة متوفرة في قاعدة كود Vue.3. تحويل سلسلة من النموذج hello-world إلى سلسلة من النموذج helloWorld
عندما يعمل العديد من المبرمجين معًا في نفس المشروع ، من المهم جدًا بالنسبة لهم الاهتمام بالأسلوب الموحد للكود. يمكن لشخص ما ، على سبيل المثال ، تسجيل بعض المعرفات المركبة في تنسيق helloWorld
، وشخص في تنسيق hello-world
. من أجل جلب النظام إلى هذه المنطقة ، يمكنك إنشاء وظيفة تحول hello-world
خطوط العرض لعرض الخطوط helloWorld
.const camelizeRE = /-(\w)/g
const camelize = cached((str) => {
return str.replace(camelizeRE, (_, c) => c ? c.toUpperCase() : '')
})
camelize('hello-world')
→ هذا هو مكان رمز Vue حيث يأتي هذا المثال.4. تحديد البيئة التي تعمل بها شفرة جافا سكريبت
في الوقت الحاضر ، نظرًا للتطور السريع للمتصفحات ، يمكن تنفيذ تعليمات JavaScript البرمجية في بيئات مختلفة. من أجل تكييف المشاريع بشكل أفضل مع البيئات المختلفة ، يجب أن تكون قادرًا على تحديد مكان تنفيذ البرامج:const inBrowser = typeof window !== 'undefined'
const inWeex = typeof WXEnvironment !== 'undefined' && !!WXEnvironment.platform
const weexPlatform = inWeex && WXEnvironment.platform.toLowerCase()
const UA = inBrowser && window.navigator.userAgent.toLowerCase()
const isIE = UA && /msie|trident/.test(UA)
const isIE9 = UA && UA.indexOf('msie 9.0') > 0
const isEdge = UA && UA.indexOf('edge/') > 0
const isAndroid = (UA && UA.indexOf('android') > 0) || (weexPlatform === 'android')
const isIOS = (UA && /iphone|ipad|ipod|ios/.test(UA)) || (weexPlatform === 'ios')
const isChrome = UA && /chrome\/\d+/.test(UA) && !isEdge
const isPhantomJS = UA && /phantomjs/.test(UA)
const isFF = UA && UA.match(/firefox\/(\d+)/)
→ هذا هو المكان الذي وجدت فيه هذا الرمز.5. التمييز بين الوظائف المضمنة والمحددة من قبل المستخدم
من المعروف أن JavaScript لديها نوعان من الوظائف. النوع الأول مدمج ، أو ، كما يطلق عليه أيضًا ، وظائف "أصلية". يتم توفير هذه الوظائف من خلال البيئة التي يتم تنفيذ التعليمات البرمجية فيها. النوع الثاني هو ما يسمى ب "وظائف المستخدم" ، أي تلك التي يكتبها المبرمجون بأنفسهم. يمكنك التمييز بين هذه الوظائف ، مع الأخذ في الاعتبار حقيقة أنه عند تحويلها إلى سلاسل ، يتم إرجاع نتائج مختلفة.Array.isArray.toString()
function fn(){}
fn.toString()
سنقوم بتجربة هذا الرمز في وحدة التحكم.ترجع طريقة toString()
الوظيفة الأصلية دائمًا بناء النموذج التالي:function fnName() { [native code] }
بمعرفة ذلك ، يمكنك كتابة دالة تسمح لك بالتمييز بين الوظائف الأصلية والمحددة من قبل المستخدم:function isNative (Ctor){
return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}
→ هذا هو المكان في قاعدة كود Vue حيث توجد مثل هذه الوظيفة.هل تمكنت من العثور على شيء مثير للاهتمام من خلال استكشاف الكود في مستودعات مشاريع جافا سكريبت الشهيرة؟![](https://habrastorage.org/webt/a_/bs/aa/a_bsaactpbr8fltzymtkhqbw1d4.png)