溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

一些手寫JavaScript常用的函數匯總

發布時間:2020-10-11 22:03:30 來源:腳本之家 閱讀:213 作者:DBCdouble 欄目:web開發

前言

在JavaScript中,幾乎每次編寫一段代碼時,通常都會寫入一個函數。我們的大部分代碼執行都是函數調用的結果。所以本文主要給大家介紹了一些JavaScript常用的函數,下面話不多說了,來一起看看詳細的介紹吧

JavaScript常用的函數

一、bind、call、apply函數的實現改變函數的執行上下文中的this指向,但不執行該函數(位于Function構造函數的原型對象上的方法)

Function.prototype.myBind = function (target) {
 if (typeof this !== 'function') {
 throw Error('myBind is not a function')
 }
 var that = this
 var args1 = [...arguments].slice(1)
 var func = function () {
 var args2 = [..arguments].slice(1)
 return that.apply(target || window, args1.concat(args2)) }
 return func
}

Function.prototype.myCall = function (context=window) {
 if (typeof this !== 'function') {
 throw Error('myBind is not a function') 
 } 
 context.fn = this
 var args = [...arguments].slice(1)
 var result = context.fn(..args) 
 delete context.fn
 return result                                                  
}

Function.prototype.myApply = function (context=window) {
 if (typeof this !== 'function') {
 throw Error('myApply is not a function')
 }
 context.fn = this
 var result
 if (argument[1]) {
 result = context.fn(...arguments[1])
 } else {
 result = context.fn()
 }
 delete context.fn
 return result
}

二、引用數據類型的深拷貝方法的實現

function cloneDeep (target) {
 function checkType(target) {
 return Object.prototype.toString.call(target).slice(8, -1)
 }
 var result, checkedType = checkType(target)
 if (checkedType === 'Array') {
 result = []
 } else if (checkedType === 'Object') {
 result = {}
 } else {
 return target
 }
 //遞歸遍歷對象或數組中的屬性值或元素為原始值為止
 for (var key in target) {
 if ( checkType(target[key]) === 'Array' || checkType(target[key]) === 'Object') {
  result[key] = cloneDeep(target[key])
 } else {
  result[key] = target[key]
 }
 }
 return result
}

思路:

  • 輸入需要深拷貝的目標target,輸出深拷貝后的結果
  • 通過Object.prototype.toString準確判斷傳入的目標target的數據類型,當target的數據類型為對象或者數組時,會對target進行遞歸遍歷直至當遍歷的數組或者對象中的數據全部為基本數據類型為止

三、數組flat函數的實現

Array.prototype.flat

四、實現n的階乘

分析:首先找規律,舉例如3的階乘等于3*2*1,也就是等于n*n-1*n-2的階乘,也就是等于3*2*1的階乘,計算到1的階乘之后,整個計算過程才結束。分析到很容易想到通過遞歸來實現這個數的階乘,因為第一,這個計算過程有規律可循,第二它有最終停止計算的出口,也就是當計算到1的時候就停止運算,以下通過遞歸來實現

function factorial (num) {
 if (num < 0) {
 throw new Error('負數沒有階乘')
 }
 if (num === 1 || num === 0) {
 return 1
 }
 return num * factorial(num-1)
}

factorial(3) //6

五、實現斐波拉契數列

分析:按照上述階乘的分析過程分析,這里不贅述

function fibonacci (n) {
 //此方法應使用尾遞歸法進行優化,這里不作優化,簡單實現
 if ( n <= 1 ) {return 1};
 return fibonacci(n - 1) + fibonacci(n - 2);}

六、實現一個計算字符串字節長度的函數

分析:首先我們要知道英文的字節長度是1,而中文的字節長度是2,但是如何判斷當前字符位是漢字還是英文呢,通過charCodeAt來判斷當前字符位的unicode編碼是否大于255,如何大于255則是漢字,那就給字符串的字節長度加2,如果小于255則是英文,就給字符串的字節長度加1,以下按照這個思路實現

function countBytesLength(str){
 var length = 0
 //首先遍歷傳入的字符串
 for(var i = 0; i < str.length; i++) {
  if (str[i].charCodeAt(i) > 255) {
   length += 2
  } else {
   length++
  }
 }
  return length
}

var str = 'DBCDouble陳'
countBytesLength(str) //11

七、實現isNaN函數

分析:要判斷傳入的值是否是"is not a number"(isNaN全拼),首先進行一個數字的隱式類型轉換,通過Number包裝類來實現Number(x),再判斷Numberz(x)的返回值是否是NaN,如果是的話再與NaN進行比對,但是由于NaN雖然是number類型的,但是是不能進行比較的,所以我們先將Number(x)返回的結果變成字符串形式,再去判斷,實現如下

function isNaN(num) {
 var ret = Number(num)
 ret += ''
 if (ret === 'NaN') {
  return true
 }
 return false
} 
isNaN('123abc') // true

八、實現數組的push函數

分析:首先push函數是位于Array構造函數的原型對象上的方法,所以要在Array.prototype上去定義,然后再分析push函數的作用是往數組的末尾添加元素,可以添加任意個數的元素,并且最終返回數組的長度,實現代碼如下

Array.prototype.push = function () {
 for (var i = 0; i< arguments.length; i++) {
  this[this.length] = arguments[i]
 }
 return this.length
}

七、實現能夠識別所有數據類型的typeof分

析:首先typeof是位于window對象上的全局方法,所以我們定義完成之后要將其掛載到window上,其次要實現識別所有數據類型包括:基本數據類型和復雜數據類型(引用數據類型),我們需要通過Object.prototype.toString方法去做才唯一能夠最準確判斷當前值為什么數據類型,實現代碼如下

window.typeof = function (value) {
 return Object.prototype.toString.call(val).slice(8, -1)
}

八、實現數組的去重方法

分析:首先因為是給所有數組實例實現一個去重方法,所以同樣是在原型鏈上進行編程

Array.prototype.unique = function () {
 //這里是利用對象鍵hash值的唯一性來去重
 var obj = {}
 var result = []
 for (var i = 0; i < this.length; i++) {
  if (!obj[this[i]]) {
   obj[this[i]] = true
   result.push(this[i])
  }
 }
 return result
}

var arr = [1,2,2,3,3]
arr.unique() //[1,2,3]
Array.prototype.unique = function () {
 //利用ES6的Array.prototype.includes
 var result = []
 for (var i = 0; i < this.length; i++) {
  if (!result.includes(this[i])) {
   result.push(this[i])
  }
 }
 return result
}
Array.prototype.unique = function () {
 //利用ES6的Set
 var result = new Set(this) //生成一個類數組
 return Array.from(result) //通過Array.from將類數組轉換成真正的數組
}
Array.prototype.unique = function () {
 //利用Array.prototype.filter返回符合條件的元素
 //利用Array.prototype.indexOf返回數組中第一次出現當前元素的索引值
 //該方法寫法最為優雅,一行代碼搞定,函數式編程
 return this.filter((item, index) => this.indexOf(item) === index)
}

九、實現函數的防抖、節流

function debounce (fn, wait=300) {
 var timer
 return function () {
  if (timer) {
   clearTimeOut(timer)
  }
  timer = setTimeout({
   fn.apply(this, arguments) 
  }, wait)
 }
}

function throttle (fn, wait=300) {
 var prev = +new Date()
 return function () {
  var now = +new Date()
  if (prev - now > 300) {
   fn.apply(this, arguments)
   prev = now
  }
 }
}

十、封裝ajax

function ajax (options) {
 options = options || {}
 options.url = options.url || ''
 options.method = options.method.toUpperCase() || 'GET'
 options.async = options.async || true
 options.data = options.data || null
 options.success = options.success || function () {}
 var xhr = null 
 if (XMLHttpRequest) {
  xhr = new XMLHttpRequest()
 } else {
  xhr = new ActiveXObject('Microsoft.XMLHTTP')
 }
 xhr.open(options.url, options.method, options.async)
 var postData = []
 for (var key in options.data) {
  postData.push(key + '='+ options.data[key])
 }
 if (options.method === 'POST') {
  xhr.open(options.method, options.url, options.async )
  xhr.send(postData)
 } else if (options.method === 'GET') {
  xhr.open(options.mehtod, options.url + postData.join('&'), options.async)
  xhr.send(null)
 }
 xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
   options.success(xhr.responseText)
  }
 }
}

十一、實現new操作符

function ajax (options) {
 options = options || {}
 options.url = options.url || ''
 options.method = options.method.toUpperCase() || 'GET'
 options.async = options.async || true
 options.data = options.data || null
 options.success = options.success || function () {}
 var xhr = null 
 if (XMLHttpRequest) {
  xhr = new XMLHttpRequest()
 } else {
  xhr = new ActiveXObject('Microsoft.XMLHTTP')
 }
 xhr.open(options.url, options.method, options.async)
 var postData = []
 for (var key in options.data) {
  postData.push(key + '='+ options.data[key])
 }
 if (options.method === 'POST') {
  xhr.open(options.method, options.url, options.async )
  xhr.send(postData)
 } else if (options.method === 'GET') {
  xhr.open(options.mehtod, options.url + postData.join('&'), options.async)
  xhr.send(null)
 }
 xhr.onreadystatechange = function () {
  if (xhr.readyState === 4 && xhr.status === 200) {
   options.success(xhr.responseText)
  }
 }
}

十二、常用六種繼承方式

1、原型鏈繼承:子類型的原型對象為父類型的實例對象

function Person (name, age) {
 this.name = name 
 this.age = age
}

Person.prototype.setName = function () {
 console.log(this.name)
}

function Student (height) {
 this.height = height
}

Student.prototype = new Person()
var stu = new Student('175')
console.log(stu)

2、借用構造函數實現繼承:在子類的構造函數中通過call調用父類的構造函數實現繼承

function Person (name, age) {
 this.name = name 
 this.age = age
}

Person.prototype.setName = function () {
 console.log(this.name)
}

function Student (height, age, name) {
 Person.call(this, age, name)
 this.height = height
}

var stu = new Studeng(175, 'cs', 24)
console.log(stu)

3、原型鏈+借用構造函數的組合繼承方式:通過在子類構造函數中通過call調用父類構造函數,繼承父類的屬性并保留傳參的優點,再通過將父類的實例作為子類的原型對象,實現繼承

function Person (name, age) {
 this.name = name 
 this.age = age
}

Person

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

亚洲午夜精品一区二区_中文无码日韩欧免_久久香蕉精品视频_欧美主播一区二区三区美女