5 اكتشافات جافا سكريبت مثيرة للاهتمام مصنوعة في كود مصدر Vue

يمكن أن تساعد قراءة الكود المصدري لأطر العمل المعروفة المبرمج على تحسين مهاراته المهنية. مؤلف المقال ، الذي ننشر ترجمته اليوم ، قام مؤخرًا بتحليل رمز vue2.x. وجد في هذا الرمز بعض أفكار جافا سكريبت المثيرة للاهتمام التي قرر مشاركتها مع الجميع.



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()  // [object Object]
_toString.call(obj) // [object Object]

سنقوم بتنفيذ هذا الرمز في وحدة تحكم أداة مطور المتصفح.


في هذه المكالمات حالة obj.toString()و Object.prototype.toString.call(obj)تؤدي إلى نفس النتائج.

هنا مثال آخر.

const _toString = Object.prototype.toString
var obj = {}
obj.toString = () => '111'
obj.toString()  // 111
_toString.call(obj) // [object Object]
/hello/.toString() // /hello/
_toString.call(/hello/) // [object RegExp]

دعونا تنفيذ التعليمات البرمجية في وحدة التحكم.


الآن ، استدعاء طريقة الكائن .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) // "Null"
toRawType(/sdfsd/) //"RegExp"

استكشف هذه الميزة في وحدة التحكم.


كما ترى ، باستخدام الوظيفة أعلاه ، يمكنك معرفة النوع الدقيق لمتغير الكائن.

هنا ، في مستودع 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')
// "helloWorld"

هذا هو مكان رمز 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 isArray() { [native code] }"
function fn(){} 
fn.toString() // "function fn(){}"

سنقوم بتجربة هذا الرمز في وحدة التحكم.


ترجع طريقة toString()الوظيفة الأصلية دائمًا بناء النموذج التالي:

function fnName() { [native code] }

بمعرفة ذلك ، يمكنك كتابة دالة تسمح لك بالتمييز بين الوظائف الأصلية والمحددة من قبل المستخدم:

function isNative (Ctor){
  return typeof Ctor === 'function' && /native code/.test(Ctor.toString())
}

→  هذا هو المكان في قاعدة كود Vue حيث توجد مثل هذه الوظيفة.

هل تمكنت من العثور على شيء مثير للاهتمام من خلال استكشاف الكود في مستودعات مشاريع جافا سكريبت الشهيرة؟


All Articles