手写 - call、apply、bind
call、apply、bind使用
代码示例:
var Tom = {name: "tom",fn: function (from, to) {console.log(`name: ${this.name}, from: ${from}, to: ${to}`)},}var Eric = {name: "eric",}Tom.fn("成都", "上海") // name: tom, from: 成都, to: 上海Tom.fn.call(Eric, "成都", "上海") // name: eric, from: 成都, to: 上海Tom.fn.apply(Eric, ["成都", "上海"]) // name: eric, from: 成都, to: 上海Tom.fn.bind(Eric, "成都", "上海")() // name: eric, from: 成都, to: 上海
相同:
- 可以让一个对象使用另一个对象的方法,并将
this指向当前对象。 -
不同:
call的参数如普通函数。apply的所有函数都是第二个参数。bind返回值是一个函数。还需要考虑实例化后对原型链的影响。call
Function.prototype.myCall = function (target, ...args) {const key = Symbol()target[key] = thisconst res = target[key](...args)target[key] = nullreturn res}
aplly
Function.prototype.myApply = function (target, args) {const key = Symbol()target[key] = thisif (args) {res = target[key](args)} else {res = target[key]()}target[key] = nullreturn res}
bind
Function.prototype.bind = function (target, ...bindArgs) {const fn = thisfunction resFn(...resArgs) {const resThis = this instanceof resFn ? this : targetreturn fn.call(resThis, ...bindArgs, ...resArgs)}function tmp() {}tmp.prototype = fn.prototyperesFn.prototype = new tmp()return resFn}
手写 - new
new做的事情:
创建一个全新的对象。
- 执行 prototype 链接。
- 使 this 指向新创建的对象。
-
代码:
function New(fn, ...args) {let obj = {__proto__: fn.prototype,}const res = fn.call(obj, ...args)if (res && (typeof res === "object" || typeof res === "function")) {return res}return obj}
手写 - instanceOf
instanceOf用来判断一个对象的prototype是否在另外一个对象的原型链上。function isInstanceOf(child, parent) {const parentPrototype = parent.prototypelet childProto = child.__proto___while (true) {// 全检测完了,没找到if (childProto === null) return falseif (childProto === parentPrototype) return truechildProto = childProto.__proto___}}
方法 - 深拷贝
function clone(obj) {if (typeof obj === "object") {const res = Array.isArray(obj) ? [] : {}for (const key in obj) {if (Object.hasOwnProperty.call(obj, key)) {obj[key] = clone(obj[key])}}return res}return obj}
方法 - 数组去重
原生js 去重
const unique = arr => {const uniqueArray = []for (let i = 0; i < arr.length; i++) {if (uniqueArray.indexOf(arr[i]) === -1) {uniqueArray.push(arr[i])}}return uniqueArray}
ES6 去重
const unique = arr => {return [...new Set(arr)]}
方法 - 防抖(debounce)
防抖(debounce),指事件触发后,在n秒内只能触发一次,若中途再次触发,则会重新计算函数的延迟时间。直到时间到达后再触发。分为了两种:
立即执行:多次触发事件,第一次会立即执行函数。之后在设定的时间内触发的事件不会触发。
非立即执行:在设定的时间内多次触发事件,只会在最后一次触发,等待设定时间结束时执行。
function debounce(fn, wait = 50, immediate) {let timer = nullreturn function () {// 如果不为null,清空定时器if (timer) clearTimeout(timer)if (immediate) {if (!timer) fn.apply(this, arguments)setTimeout(() => {timer = null}, wait)} else {timer = setTimeout(() => {fn.apply(this, arguments)}, wait)}}}
方法 - 节流(throttle)
多次触发事件,在指定时间间隔内只会触发一次。
function throttle(fn, wait) {let prev = new Date()return function () {let now = new Date()if (now - prev > wait) {prev = nowfn.apply(this, arguments)}}}
算法 - 斐波那契数列
function fibonacci(n) {if (n === 1 || n === 2) {return 1}return fibonacci(n - 2) + fibonacci(n - 1)}
function fibonacci(n) {let n1 = 1let n2 = 1let sum = 1for (let i = 2; i < n; i++) {sum = n1 + n2n1 = n2n2 = sum}}
算法 - 冒泡排序
function sort(arr) {for (let j = 0; j < arr.length; j++) {for (let i = 0; i < arr.length - j; i++) {if (arr[i] > arr[i + 1]) {const prev = arr[i]arr[i] = arr[i + 1]arr[i + 1] = prev}}}}
算法 - 快速排序
