ในงานพัฒนาของฉันฉันมักจะพบกับสถานการณ์ที่ฉันต้องการตรวจสอบว่าฟังก์ชั่นเป็นฟังก์ชั่นดั้งเดิมของ JavaScript หรือไม่ บางครั้งนี่เป็นงานที่จำเป็นมาก คุณจำเป็นต้องรู้ว่าฟังก์ชั่นนี้จัดทำโดยเบราว์เซอร์หรือไม่หรือถูกห่อหุ้มและปลอมตัวเป็นฟังก์ชั่นดั้งเดิมโดยบุคคลที่สาม แน่นอนวิธีที่ดีที่สุดคือการตรวจสอบค่าการส่งคืนของวิธีการ toString ที่ดำเนินการฟังก์ชั่นนี้
จาวาสคริปต์
วิธีการทำภารกิจนี้ให้สำเร็จนั้นง่ายมาก:
การคัดลอกรหัสมีดังนี้:
ฟังก์ชั่น isnative (fn) {
return (// {/s*/[รหัสดั้งเดิม/]/s*/}/). ทดสอบ ('' + fn);
-
วิธีการ ToString จะส่งคืนรูปแบบสตริงของวิธีนี้จากนั้นใช้นิพจน์ทั่วไปเพื่อกำหนดอักขระที่มีอยู่ในนั้น
วิธีที่แข็งแกร่งขึ้น
John-David Dalton ผู้ก่อตั้ง Lodash พบทางออกที่ดีกว่า:
การคัดลอกรหัสมีดังนี้:
;(การทำงาน() {
// ใช้เพื่อแก้ไขภายใน `[[คลาส]]` ของค่า
var toString = object.prototype.toString;
// ใช้เพื่อแก้ไขแหล่งที่มาของฟังก์ชั่นที่ถอดรหัส
var fntostring = function.prototype.toString;
// ใช้ในการตรวจจับตัวสร้างโฮสต์ (Safari> 4; อาร์เรย์ที่พิมพ์จริงจริงๆ)
var rehostctor =/^/[object.+? constructor/] $/;
// รวบรวม regexp โดยใช้วิธีการทั่วไปทั่วไปเป็นเทมเพลต
// เราเลือก `Object#ToString` เพราะมีโอกาสที่ดีที่มันไม่ได้ถูกโคลน
var renative = regexp ('^' +
// coerce `Object#ToString` กับสตริง
สตริง (toString)
// หลบหนีอักขระ regexp พิเศษใด ๆ
.replace (/[.*+?^$ {} () | [/] /////]/g, '// $ &')
// แทนที่การกล่าวถึงของ `toString` ด้วย`.*? `เพื่อให้เทมเพลตทั่วไป
// แทนที่สิ่งต่างๆเช่น `สำหรับ ... ` เพื่อรองรับสภาพแวดล้อมเช่นแรดซึ่งเพิ่มข้อมูลเพิ่มเติม
// เช่น Method Arity
.replace (/toString | (ฟังก์ชั่น).*? (? = /// () | สำหรับ. +? (? = ///])/g, '$ 1*?') + '$'
-
ฟังก์ชั่น isnative (ค่า) {
var type = typeof value;
return type == 'function'
// ใช้ `function#toString` เพื่อข้ามวิธี 'ToString' ของค่าของค่าของตัวเอง
// และหลีกเลี่ยงการแกล้งทำ
- Renative.test (fntostring.call (ค่า))
// ทางเลือกกลับไปที่การตรวจสอบวัตถุโฮสต์เนื่องจากสภาพแวดล้อมบางอย่างจะเป็นตัวแทน
// สิ่งต่าง ๆ เช่นอาร์เรย์ที่พิมพ์เป็นวิธี DOM ซึ่งอาจไม่สอดคล้องกับไฟล์
// รูปแบบดั้งเดิมปกติ
: (value && type == 'object' && rehostctor.test (toString.call (ค่า))) || เท็จ;
-
// ส่งออกตามที่คุณต้องการ
module.exports = isnative;
-
ตอนนี้คุณเห็นมันเหมือนกันมันซับซ้อนมาก แต่มีพลังมากขึ้น แน่นอนว่านี่ไม่ใช่เพื่อการป้องกันความปลอดภัย แต่เพียงแค่ให้ข้อมูลที่เกี่ยวข้องกับคุณว่าเป็นฟังก์ชั่นดั้งเดิมหรือไม่