1、如何在ES5 下面实现let
(function(){
for(var i = 0; i < 5; i ++){
console.log(i) // 0 1 2 3 4
}
})();
console.log(i) // Uncaught ReferenceError: i is not defined
babel 转
for(let i=0;i<10;i++>){
console.log(i)
}
console.log(i)
// 转成如下
for(var _i=0;_i<10;_i++>){
console.log(_i)
}
console.log(i) // Uncaught ReferenceError: i is not defined
2、如何在ES5环境下实现const
// Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
function _const(key, value) {
const desc = {
value,
writable: false
}
Object.defineProperty(window, key, desc)
}
_const('obj', {a: 1}) //定义obj
obj.b = 2 //可以正常给obj的属性赋值
obj = {} //无法赋值新对象
3、手写bind
if(Function.prototype._bind === undefined){
Function.prototype._bind = function (ctx){
let args = [].slice.call(arguments,1)
let that = this
return function (){
that.apply(ctx,args.concat([].slice(arguments,1)))
}
}
}
4、手写call
Function.prototype.call = function call(ctx,...args){
ctx = ctx || window
ctx.fn = this
let result = ctx.fn(...args)
delete ctx.fn
return result
}
5、手写apply
Function.prototype.apply = function call(ctx,args){
ctx = ctx || window
ctx.fn = this
let result = ctx.fn(...args)
delete ctx.fn
return result
}
6、手写new
function new (){
let obj = {}
let Constructor= [].shift.call(arguments)
obj.__proto__ = Constructor.prototype
let result = Constructor.apply(obj,arguments)
return result instanof Object?result:obj
}
7、手写map
function map(arr, mapCallback) {
// 首先,检查传递的参数是否正确。
if (!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function') {
return [];
} else {
let result = [];
// 每次调用此函数时,我们都会创建一个 result 数组
// 因为我们不想改变原始数组。
for (let i = 0, len = arr.length; i < len; i++) {
result.push(mapCallback(arr[i], i, arr));
// 将 mapCallback 返回的结果 push 到 result 数组中
}
return result;
}
}
8、手写filter
function filter(arr, filterCallback) {
// 首先,检查传递的参数是否正确。
if (!Array.isArray(arr) || !arr.length || typeof filterCallback !== 'function')
{
return [];
} else {
let result = [];
// 每次调用此函数时,我们都会创建一个 result 数组
// 因为我们不想改变原始数组。
for (let i = 0, len = arr.length; i < len; i++) {
// 检查 filterCallback 的返回值是否是真值
if (filterCallback(arr[i], i, arr)) {
// 如果条件为真,则将数组元素 push 到 result 中
result.push(arr[i]);
}
}
return result; // return the result array
}
}
9、手写reduce
function reduce(arr, reduceCallback, initialValue) {
// 首先,检查传递的参数是否正确。
if (!Array.isArray(arr) || !arr.length || typeof reduceCallback !== 'function')
{
return [];
} else {
// 如果没有将initialValue传递给该函数,我们将使用第一个数组项作为initialValue
let hasInitialValue = initialValue !== undefined;
let value = hasInitialValue ? initialValue : arr[0]
// 如果有传递 initialValue,则索引从 1 开始,否则从 0 开始
for (let i = hasInitialValue ? 0 : 1, len = arr.length; i < len; i++) {
value = reduceCallback(value, arr[i], i, arr);
}
return value;
}}
10、手写intanceof
// instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。
// left:obj right:Function
function myInstanceof(left, right) {
let prototype = right.prototype
left = left.__proto__
while (true) {
if (left === null || left === undefined)
return false
if (prototype === left)
return true
left = left.__proto__
}
}
11、防抖:触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则重新计算时间
function debounce(fn) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments)
}, 500)
}
}
function sayHi() {
console.log("防抖成功")
}
var inp = document.getElementById('inp')
inp.addEventListener('input', debounce(sayHi))
12、节流:高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率
function throttle(fn) {
let canRun = true;
return function () {
if (!canRun) return
canRun = false
fn.apply(this, arguments)
setTimeout(() => {
canRun = true
}, 500)
}
}
function sayHi(e) {
console.log(e.target.innerHeight, e.target.innerWidth)
}
window.addEventListener('resize', throttle(sayHi))
13、简单深拷贝deepClone
function deepClone (source){
if(!source && typeof source !== 'object'){
throw new error("please insert object")
}
let target = source.constructor === Array ? []:{}
Object.keys(source).forEach(keys =>{
if(source[keys] && typeof source[keys] === 'object'){
target[keys] = deepClone(source[keys])
}else{
target[keys] = source[keys]
}
})
return target
}
console.log(deepClone([,3,4]))
}
14、手写promise
class myPromise {
constructor(executor){
this._resloveQueue =[]
this._rejectQueue = []
let _reslove = (val)=>{
while (this._resloveQueue.length) {
const callback = this._resloveQueue.shift()
callback(val)
}
}
let _reject = (val)=>{
while (this._rejectQueue.length > 0) {
const callback =this._rejectQueue.shift()
callback(val)
}
}
executor(_reslove,_reject)
}
then(resloveFn,rejectFn){
this._resloveQueue.push(resloveFn)
this._rejectQueue.push(rejectFn)
}
}
const p1 = new myPromise((reslove,reject)=>{
setTimeout(() => {
reslove("reslut")
}, 1000);
})
p1.then(res => console.log(res))