时间:2021-07-01 10:21:17 帮助过:24人阅读
前言
在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 }
思路:
三、数组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
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对脚本之家的支持。