10道高频JavaScript手写面试题及答案
JavaScript笔试部分 深拷贝(deepclone) 简单版:
1 const newObj = JSON .parse(JSON .stringify(oldObj));
局限性 :
实现Event (event bus)
event bus既是node中各个模块的基石,又是前端组件通信的依赖手段之一,同时涉及了订阅-发布设计模式,是非常重要的基础。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class EventEmeitter { constructor (){ this ._events = this ._events || new Map (); this ._maxListeners = this ._maxListeners || 1 o; } } EventEmeitter.prototype.emit = function (type,...args ) { let hander; handler = this ._events.get(type); if (args.length > 0 ) { hander.apply(this ,args); }else { handler.call(this ); } return true ; }; EventEmeitter.prototype.addListener = function (type,fn ) { if (!this ._events.get(type)) { this ._events.set(type,fn); } };
实现instanceOf 1 2 3 4 5 6 7 8 9 10 11 12 function instance_of (L,R ) { var O = R.prototype; L = L.__proto__; while (true ) { if (L === null ) return false ; if (O === L) return true ; L = L.__proto__; } }
模拟new new操作符做了这些事:
他创建了一个全新的对象
他会被执行[[Prototype]] (也就是proto ) 链接
它使this指向新创建的对象
通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上
如果函数没有返回对象类型Object(包含Function,Array,Date,RegExg,Error),那么new表达式中的函数调用将返回对象引用
1 2 3 4 5 6 7 8 9 10 11 function objectFactory ( ) { const obj = new object(); const Constructor = [].shift.call(arguments ); obj.__proto__ = Constructor.prototype; const ret = Constructor.apply(obj,arguments ); return typeof ret === "object" ? ret : obj; }
实现一个call call做了什么:
将函数设为对象的属性
执行&删除这个函数
指定this到函数并传人给定参数执行函数
如果不传人参数,默认指向为 window
1 2 3 4 5 6 7 8 9 10 11 12 13 14 Function .prototype.myCall = function (context ) { context.fn = this ; let args = []; for (let i = 1 ,len = arguments .length,i < len; i++){ args.push(arguments [i]); } context.fn(...args); let result = context.fn(...args); delete context.fn; return result; };
实现apply方法 apply原理与call很相似 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Function .prototype.myapply = function (context,arr ) { var context = Object (context) || window ; context.fn = this ; var result; if (!arr){ result = context.fn(); }else { var args = []; for (var i = 0 ,len = arr.length;i < len; i++){ args.push("arr[" + i +"]" ); } result = eval ("context.fn(" + args + ")" ); } delete context.fn; return result; }
实现bind 实现bind要做什么
返回一个函数,绑定this,传递预置参数
bind返回的函数可以作为构造函数使用。故作为构造函数时应使得this失效,但是传人的参数依然有效
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 if (!Function .prototype.bind) { Function .prototype.bind = function (oThis ) { if (typeof this !== 'function' ) { throw new TypeError ('Function.prototype.bind - what is trying to be bound is not callable' ); } var aArgs = Array .prototype.slice.call(arguments , 1 ), fToBind = this , fNOP = function ( ) {}, fBound = function ( ) { return fToBind.apply(this instanceof fBound ? this : oThis, aArgs.concat(Array .prototype.slice.call(arguments ))); }; if (this .prototype) { } fBound.prototype = new fNOP(); return fBound; }; } 详解请移步JavaScript深入之bind的模拟实现 #12 模拟Object .create Object .create()方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。function create (proto ) { function F ( ) {} F.prototype = proto; return new F(); }
模拟Object.create Object.create()方法创建一个新对象,使用现有的对象来提供新创建的对象的proto . 1 2 3 4 5 6 7 8 function create (proto ) { function F ( ) { F.prototype=protp; return new F() } }
解析 URL Params为对象 1 2 3 4 5 6 7 8 9 10 let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled'; parseParam(url) /* 结果 { user: 'anonymous', id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型 city: '北京', // 中文需解码 enabled: true, // 未指定值得 key 约定为 true } */
转化为驼峰,命名 1 2 3 4 5 6 7 8 let s1= "get-element-by-id" let f = function (s ) { return s.replace(/-\w/g ,function (x ) { return x.slice(1 ).toUpperCase(); }) }
声明:文章著作权归作者所有,如有侵权,请联系删除。