5 个提升你 JavaScript 编码水平的实例


5 个提升你 JavaScript 编码水平的实例

文章插图
 
虽然 2020 的今天,各种前端框架、工具林立,而这些框架跟工具也帮我们提前解决了不少麻烦的问题,但是工具始终是工具,扎实的基本功才是最核心的,现在一起来通过几个实际的代码片段来提高我们原生 JS 的编码水平 。
判断数据类型首先来提问一个:typeof是否能正确判断类型?
答案是:不可以,因为由于历史原因,在判断原始类型时,typeof null会等于object 。而且对于对象来说,除了函数,都会转换成object 。例子如下:
typeof 1; // 'number'typeof "1"; // 'string'typeof null; //typeof []; // 'object'typeof {}; // 'object'typeof window.alert; // 'function'再来提问一个,instanceof是否能正确判断类型?
答案是:还是不可以,虽然instanceof是通过原型链来判断的,但是对于对象来说,Array也会被转换成Object,而且也不能区分基本类型string和boolean 。例如:
function Func() {}const func = new Func();console.log(func instanceof Func); // trueconst obj = {};const arr = [];obj instanceof Object; // truearr instanceof Object; // truearr instanceof Array; // trueconst str = "abc";const str2 = new String("abc");str instanceof String; // falsestr2 instanceof String; // true所以该怎么办呢?
这时候我们可以使用:Object.prototype.toString.call()
所以为什么?
因为每个对象都有一个toString()方法,当要将对象表示为文本值或以预期字符串的方式引用对象时,会自动调用该方法 。默认情况下,从Object派生的每个对象都会继承toString()方法 。如果此方法未在自定义对象中被覆盖,则toString()返回[Object type],其中type是对象类型 。所以就有以下例子:
Object.prototype.toString.call(new Date()); // [object Date]Object.prototype.toString.call("1"); // [object String]Object.prototype.toString.call(1); // [object Numer]Object.prototype.toString.call(undefined); // [object Undefined]Object.prototype.toString.call(null); // [object Null]所以综合上述知识点,我们可以封装出以下通用类型判断方法:
var type = function(data) {var toString = Object.prototype.toString;var dataType = data instanceof Element? 'element' // 为了统一DOM节点类型输出: toString.call(data).replace(/[objects(.+)]/, ''$1').toLowerCase()return dataType}使用方法如下:
type("a"); // stringtype(1); // numbertype(window); // windowtype(document.querySelector("h1")); // element通用的数组/类数组对象封装如果我们使用 ES5/ES6+的数组 API,很容易就能够对数组进行各类的循环操作,但是如果我们要循环一个类数组对象呢?
例如NodeList 。直接循环是会报错的:
document.querySelectorAll("div").map(e => e); // Uncaught TypeError: document.querySelectorAll(...).map is not a function当然我们可以用扩展运算符:
[...document.querySelectorAll("div")].map(e => e);那如果我们不用扩展运算符呢?
那么我们就可以利用call的特性,将NodeList里的元素一个一个的插入到数组中,例子如下:
【5 个提升你 JavaScript 编码水平的实例】var listMap = function(array, type, fn) {return !fn ? array : Array.prototype[type]["call"](array, fn);};使用方法如下:
var divs = document.querySelectorAll("div");listMap(divs, "forEach", function(e) {console.log(e);});获取 dom 元素节点的偏移量如果有用过jQuery的童鞋,就一定不会忘记$('').offset()这个 api 的强大功能,这个 api 可以轻易获取元素的偏移量,那么如果我们不用jQuery该怎么实现呢?
我们先来看看例子:
var getOffset = function(el) {var scrollTop =el.getBoundingClientRect().top +document.body.scrollTop +document.documentElement.scrollTop;var scrollLeft =el.getBoundingClientRect().left +document.body.scrollLeft +document.documentElement.scrollLeft;return {top: scrollTop,left: scrollLeft};};首先我们先来看getBoundingClientRect()这个方法 。
getBoundingClientRect()方法返回元素的大小及其相对于视口的位置 。返回值是一个 DOMRect 对象,是与该元素相关的 css 边框集合。
然后就是document.body.scrollTop 跟 document.documentElement.scrollTop这两个是一个功能,只不过在不同的浏览器下会有一个始终为 0,所以做了以上的兼容性处理 。所以当我们做拖拽功能的时候,就可以依赖上以上属性 。
使用方法如下:


推荐阅读