JS面试知识点总结(十七)
|字数总计:1.3k|阅读时长:5分钟|阅读量:|
手写一个 jsonp
function jsonp(url, params, callback) { let queryString = url.indexOf("?") === -1 ? "?" : "&";
for (var k in params) { if (params.hasOwnProperty(k)) { queryString += k + "=" + params[k] + "&"; } }
let random = Math.random() .toString() .replace(".", ""), callbackName = "myJsonp" + random;
queryString += "callback=" + callbackName;
let scriptNode = document.createElement("script"); scriptNode.src = url + queryString;
window[callbackName] = function() { callback(...arguments);
document.getElementsByTagName("head")[0].removeChild(scriptNode); };
document.getElementsByTagName("head")[0].appendChild(scriptNode); }
|
详细资料可以参考:
《原生 jsonp 具体实现》
《jsonp 的原理与实现》
手写一个观察者模式?
var events = (function() { var topics = {};
return { subscribe: function(topic, handler) { if (!topics.hasOwnProperty(topic)) { topics[topic] = []; } topics[topic].push(handler); },
publish: function(topic, info) { if (topics.hasOwnProperty(topic)) { topics[topic].forEach(function(handler) { handler(info); }); } },
remove: function(topic, handler) { if (!topics.hasOwnProperty(topic)) return;
var handlerIndex = -1; topics[topic].forEach(function(item, index) { if (item === handler) { handlerIndex = index; } });
if (handlerIndex >= 0) { topics[topic].splice(handlerIndex, 1); } },
removeAll: function(topic) { if (topics.hasOwnProperty(topic)) { topics[topic] = []; } } }; })();
|
详细资料可以参考:
《JS 事件模型》
EventEmitter 实现
class EventEmitter { constructor() { this.events = {}; }
on(event, callback) { let callbacks = this.events[event] || []; callbacks.push(callback); this.events[event] = callbacks;
return this; }
off(event, callback) { let callbacks = this.events[event]; this.events[event] = callbacks && callbacks.filter(fn => fn !== callback);
return this; }
emit(event, ...args) { let callbacks = this.events[event]; callbacks.forEach(fn => { fn(...args); });
return this; }
once(event, callback) { let wrapFun = (...args) => { callback(...args);
this.off(event, wrapFun); }; this.on(event, wrapFun);
return this; } }
|
一道常被人轻视的前端 JS 面试题
function Foo() { getName = function() { alert(1); }; return this; } Foo.getName = function() { alert(2); }; Foo.prototype.getName = function() { alert(3); }; var getName = function() { alert(4); }; function getName() { alert(5); }
Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();
|
详细资料可以参考:
《前端程序员经常忽视的一个 JavaScript 面试题》
《一道考察运算符优先级的 JavaScript 面试题》
《一道常被人轻视的前端 JS 面试题》
Performance API 用于精确度量、控制、增强浏览器的性能表现。这个 API 为测量网站性能,提供以前没有办法做到的精度。
使用 getTime 来计算脚本耗时的缺点,首先,getTime方法(以及 Date 对象的其他方法)都只能精确到毫秒级别(一秒的千分之一),想要得到更小的时间差别就无能为力了。其次,这种写法只能获取代码运行过程中的时间进度,无法知道一些后台事件的时间进度,比如浏览器用了多少时间从服务器加载网页。
为了解决这两个不足之处,ECMAScript 5引入“高精度时间戳”这个 API,部署在 performance 对象上。它的精度可以达到1毫秒 的千分之一(1秒的百万分之一)。
navigationStart:当前浏览器窗口的前一个网页关闭,发生 unload 事件时的 Unix 毫秒时间戳。如果没有前一个网页,则等于 fetchStart 属性。
loadEventEnd:返回当前网页 load 事件的回调函数运行结束时的 Unix 毫秒时间戳。如果该事件还没有发生,返回 0。
|
根据上面这些属性,可以计算出网页加载各个阶段的耗时。比如,网页加载整个过程的耗时的计算方法如下:
var t = performance.timing; var pageLoadTime = t.loadEventEnd - t.navigationStart;
|
详细资料可以参考:
《Performance API》
js 中的命名规则
(1)第一个字符必须是字母、下划线(_)或美元符号($) (2)余下的字符可以是下划线、美元符号或任何字母或数字字符
一般我们推荐使用驼峰法来对变量名进行命名,因为这样可以与 ECMAScript 内置的函数和对象命名格式保持一致。
|
详细资料可以参考:
《ECMAScript 变量》
js 语句末尾分号是否可以省略?
在 ECMAScript 规范中,语句结尾的分号并不是必需的。但是我们一般最好不要省略分号,因为加上分号一方面有 利于我们代码的可维护性,另一方面也可以避免我们在对代码进行压缩时出现错误。
|
Object.assign()
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
|
Math.ceil 和 Math.floor
Math.ceil() === 向上取整,函数返回一个大于或等于给定数字的最小整数。
Math.floor() === 向下取整,函数返回一个小于或等于给定数字的最大整数。
|
js for 循环注意点
for (var i = 0, j = 0; i < 5, j < 9; i++, j++) { console.log(i, j); }
|