持续更新常见JavaScript算法
# 12300 transform 12,300 function thousandSeparator(number) { let result = []; let rest = String(Math.abs(number)); while (rest.length) { result.push(rest.slice(-3)); rest = rest.slice(0, -3); } const r = result.reverse().join(","); return number < 0 ? "-" + r : r } console.log(666, thousandSeparator(12300))
Array.prototype.myReduce = function (callback, initialValue) { let arr = this; let pre = initialValue ? initialValue : arr[0]; let i = initialValue ? 0 : 1; for (i; i < arr.length; i++) { pre = callback(pre, arr[i]); } return pre; } const res = [1, 2, 3, 4].myReduce((pre, cur) => { return pre + cur; }, 1); console.log('myReduce', res);
var Person = function (name, age) { this.name = name; this.age = age; } Person.prototype.test = "this is a test"; Person.prototype.testFunc = function () { console.log('this is a testFunc'); } // 子类 var Student = function (name, age, gender, score) { Person.apply(this, [name, age]); // 盗用构造函数 this.gender = gender; this.score = score; } // 1. 改变 Student 构造函数的原型对象 // Student.prototype = new Person(); // 2.圣杯模式 Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; Student.prototype.testStuFunc = function () { console.log('this is a testStuFunc'); } // 测试 var zhangsan = new Student("张三", 18, "男", 100); console.log(zhangsan.name); // 张三 console.log(zhangsan.age); // 18 console.log(zhangsan.gender); // 男 console.log(zhangsan.score); // 100 console.log(zhangsan.test); // this is a test zhangsan.testFunc(); // this is a testFunc zhangsan.testStuFunc(); // this is a testStuFunc console.log(Student.prototype)
function P(age, country) { console.log(`Hello, my name is ${this.name} and I am ${age}, I am from ${country}`); } /* 1. call 函数允许你在特定上下文中调用函数 function.call(context, arg1, arg2, ...) 2. apply 函数与 call 函数类似,也允许你在特定上下文中调用函数。不同之处在于 apply 函数需要以数组形式传递参数 function.apply(context, [argsArray]) 1. bind 函数与 call 和 apply 函数不同。它不会立即调用函数。而是返回一个将绑定到指定上下文的新函数, 当调用该函数时,它将以指定的上下文运行。 function.bind(thisArg, arg1, arg2, ...) */ P.call({name: 'mary'}, '12', 'USA') P.apply({name: 'lilei'}, ['13', 'France']) P.bind({name: 'tom'}, '11', 'China') // 5. 自定义call、apply、bind // 实现call方法 Function.prototype.myCall = function (context, ...args) { // 如果context参数为空,则默认为window对象 context = context || window; // 使用Symbol函数创建唯一标识符 const fnSymbol = Symbol(); // 将原始函数存储为context对象的属性 context[fnSymbol] = this; // 调用函数并将结果存储在 result 变量中 const result = context[fnSymbol](...args); // 删除 context 对象的属性 delete context[fnSymbol]; // 返回函数的结果 return result; }; // 实现 apply 方法 Function.prototype.myApply = function (context, args) { // 如果 context 参数为空,则默认为 window 对象 context = context || window; // 使用 Symbol 函数创建唯一标识符 const fnSymbol = Symbol(); // 将原始函数存储为 context 对象的属性 context[fnSymbol] = this; // 调用函数并将结果存储在 result 变量中 const result = context[fnSymbol](...args); // 删除 context 对象的属性 delete context[fnSymbol]; // 返回函数的结果 return result; }; // 实现 bind 方法 Function.prototype.myBind = function (context, ...args) { // 将 this 绑定到 fn 变量中 const fn = this; // 返回一个新函数,该函数将传递的参数与新函数的参数合并,并在新上下文中使用 apply 调用原始函数 return function (...newArgs) { return fn.apply(context, [...args, ...newArgs]); }; }; P.myCall({name: 'mary'}, '12', 'USA') P.myApply({name: 'lilei'}, ['13', 'France']) P.myBind({name: 'tom'}, '11', 'China')
const checkIfInstanceOf = (obj, classFunction) => { if (classFunction === null) return false; while (obj !== null) { if (obj.__proto__ === classFunction.prototype) { return true }; obj = obj.__proto__; } return false; } class Animal {}; class Dog extends Animal {}; console.log('checkIfInstanceOf', checkIfInstanceOf(new Date(), Date)) // true console.log('checkIfInstanceOf', checkIfInstanceOf(new Dog(), Animal)) // true console.log('checkIfInstanceOf', checkIfInstanceOf(Date, Date)) // false console.log('checkIfInstanceOf', checkIfInstanceOf(5, Number)) // true console.log('checkIfInstanceOf', checkIfInstanceOf([], Array)) // true
Array.prototype.last = function() { const len = this.length return len ? this[len - 1] : -1 } console.log([1, 2, 3].last()); // 3 console.log([].last()); // -1
/** * @param {number} n * @return {Function} counter */ var createCounter = function(n) { return function() { return n++ }; }; const counter = createCounter(10) counter() // 10 counter() // 11 counter() // 12
/** * @param {number} millis * @return {Promise} */ async function sleep(millis) { return new Promise((resolve, reject) => { setTimeout(resolve, millis) }) } let t = Date.now() sleep(100).then(() => console.log(Date.now() - t)) // 100
/** * @param {Array} arr * @param {number} depth * @return {Array} */ Array.prototype.myFlat = function(deep) { let arr = this; let result = []; if (deep === 0) { return arr; } for (let i = 0; i < arr.length; i++) { if (Array.isArray(arr[i])) { result.push(...arr[i].myFlat(deep - 1)); } else { result.push(arr[i]); } } return result; } console.log('myFlat', [1,2,3,[4,5,6],[7,8,[9,10,11],12],[13,14,15]].myFlat(2))
Number.prototype.add = function(n) { return this + n } Number.prototype.sub = function(n) { return this - n } console.log('(5).add(3).sub(2)',(5).add(3).sub(2)) // 6
const myAdd = (min, max) => { let sum = 0 for (let i = min; i <= max; i++) { sum = sum + i } return sum } console.log('myAdd', myAdd(1, 100))
// 在西雅图的公司远程工作,因为月中算法考核,半月的绩效奖金没了。。。 const intersect = function (nums1, nums2) { let result = [] let longArr = nums1.length > nums2.length ? nums1 : nums2; let shortArr = nums1.length > nums2.length ? nums2 : nums1; for (let i = 0; i < shortArr.length; i++) { let longIndex = longArr.indexOf(shortArr[i]) if (longIndex != -1) { result.push(longArr.splice(longIndex, 1)[0]) } } return result }; intersect([1,2,1,2], [2,2,2]) // [2, 2, 2] intersect([4,9,5], [9,4,9,8,4]) // [4, 9] intersect([3,1,2], [2,2]) // [2]
/** * @param {number[]} nums * @return {number[]} */ const sortArray = function (nums) { const { length } = nums; for (let i = 0; i < length; i++) { for (let j = 0; j < length - 1 - i; j++) { if (nums[j] > nums[j + 1]) { [nums[j], nums[j + 1]] = [nums[j + 1], nums[j]]; } } } return nums; }; sortArray([1, 3, 9, 5, 2, 4, 6])
/* 在这种情况下,curry 函数接受一个函数 fn 作为参数,并返回一个经过 currying 的新函数。 在调用 curryed 函数时,它会检查传入的参数数量是否大于或等于原函数 fn 的参数数量(arity)。 如果是,则直接调用原函数;否则,它会返回一个接受剩余参数(rest)的新函数,并将之前传入的参数(args)与剩余参数合并,然后再调用 curryed 函数。这样就实现了函数 currying。 */ const curry = (fn) => { const arity = fn.length; return function curried(...args) { if (args.length >= arity) { return fn.apply(this, args); } else { return function (...rest) { return curried.apply(this, args.concat(rest)); }; } }; } const getURL = (protocol, domain, path) => { return protocol + "://" + domain + "/" + path; } const myurl = getURL('http', 'mysite', 'home.html'); const myurl2 = getURL('http', 'mysite', 'about.html'); console.log('myurl', myurl); console.log('myurl2', myurl2); const curry = (fn) => { const arity = fn.length; return function curried(...args) { if (args.length >= arity) { return fn.apply(this, args); } else { return function (...rest) { return curried.apply(this, args.concat(rest)); }; } }; } const getURL = (protocol, domain, path) => { return protocol + "://" + domain + "/" + path; } const myurl = getURL('http', 'mysite', 'home.html'); const myurl2 = getURL('http', 'mysite', 'about.html'); console.log('myurl', myurl); console.log('myurl2', myurl2); // 减少重复传递不变的参数 const superGetURL = curry(getURL)('https', 'mysite'); const myurl3 = superGetURL('detail.html') console.log('myurl3', myurl3);
var Person = function (name, age) { this.name = name; this.age = age; } Person.prototype.test = "this is a test"; Person.prototype.testFunc = function () { console.log('this is a testFunc'); } var Student = function (name, age, gender, score) { Person.apply(this, [name, age]);// Stealing the constructor this.gender = gender; this.score = score; } Student.prototype = new Person(); // Change the prototype object of the Student constructor Student.prototype.testStuFunc = function () { console.log('this is a testStuFunc'); } // 测试 var zhangsan = new Student("张三", 18, "男", 100); console.log(zhangsan.name); // 张三 console.log(zhangsan.age); // 18 console.log(zhangsan.gender); // 男 console.log(zhangsan.score); // 100 console.log(zhangsan.test); // this is a test zhangsan.testFunc(); // this is a testFunc zhangsan.testStuFunc(); // this is a testStuFunc