肥宅钓鱼网
当前位置: 首页 钓鱼百科

一个简单的javascript代码(5个提升你JavaScript)

时间:2023-08-18 作者: 小编 阅读量: 2 栏目名: 钓鱼百科

而且对于对象来说,除了函数,都会转换成object。因为每个对象都有一个toString()方法,当要将对象表示为文本值或以预期字符串的方式引用对象时,会自动调用该方法。默认情况下,从Object派生的每个对象都会继承toString()方法。getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。返回值是一个DOMRect对象,是与该元素相关的CSS边框集合。

虽然 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(/\[object\s(. )\]/, ''$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里的元素一个一个的插入到数组中,例子如下:

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().topdocument.body.scrollTopdocument.documentElement.scrollTop;var scrollLeft =el.getBoundingClientRect().leftdocument.body.scrollLeftdocument.documentElement.scrollLeft;return {top: scrollTop,left: scrollLeft};};

首先我们先来看getBoundingClientRect()这个方法。

getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。返回值是一个 DOMRect 对象,是与该元素相关的 CSS 边框集合 。

然后就是document.body.scrollTop 跟 document.documentElement.scrollTop这两个是一个功能,只不过在不同的浏览器下会有一个始终为 0,所以做了以上的兼容性处理。所以当我们做拖拽功能的时候,就可以依赖上以上属性。

使用方法如下:

var el = document.querySelector(".moveBox");getOffset(el); // {top: xxx, left: xxx}

我们可以看上面的摇杆效果,这里就是利用了offset()去做位置判断。具体实现代码可以看:https://codepen.io/krischan77/pen/zYxPNPy

Fade 特效

// Fade invar fadeIn = function (el) {el.style.opacity = 0var last =new Date()var tick = function() {el.style.opacity =el.style.opacity(new Date() - last) / 400last =new Date()if ( el.style.opacity < 1) {requestAnimationFrame(tick))}}tick()}// Fade outvar fadeOut = function (el) {el.style.opacity = 1var last =new Date()var tick = function() {el.style.opacity =el.style.opacity - (new Date() - last) / 400last =new Date()if ( el.style.opacity > 0) {requestAnimationFrame(tick)}}tick()}

上述是淡入淡出效果的具体实现,这里是利用requestAnimationFrame对opacity通过递归的方式进行修改。

其实这里需要提一个概念,就是时间分片

这是一个非常重要的概念,例如 ReactFiber 核心实现就是时间分片。它会将一个长任务切分成一个含有若干小任务的任务队列,然后一个接着一个的执行。

requestAnimationFrame就是这样一个 API,它可以根据系统来决定回调函数的执行时机,其实也就是在下一次重绘之前更新动画帧,因为有这样的机制,所以能防止丢帧。

利用队列的概念进行数据操作

队列(queue),是先进先出(FIFO, First-In-First-Out)的线性表。在具体应用中通常用链表或者数组来实现。队列只允许在后端(称为 rear)进行插入操作,在前端(称为 front)进行删除操作。

虽然很多人觉得了解数据结构对前端作用不大,但是如果我们懂一些基础的概念,是否在编码时能够更加扩散我们的思维呢?我们看下面两个例子:

获取节点在该父节点下的坐标。

如果我们要操作原生 DOM,那么是绕不开获取节点在该父节点的下标的这个功能的,那么我们该如何实现呢?

当然就是利用我们的循环啦,对子元素集合进行遍历,直到确定下标为止,代码如下:

var index = function(el) {if (!el) {return -1;}var i = 0;while ((el = el.previousElementSibling)) {i;}return i;};

清空子节点

如果我们要清空某个 DOM 节点的子节点,我们有以下的方法:

var empty = function(el) {while (el.firstChild) {el.removeChild(el.firstChild);}};

上面只是提供一个思路,其实el.innerHTML = ''会更简洁。

利用 reduce 进行数据优化数组去重

没错,又是一个老生常谈的问题,数组去重,但是我们这次去除的不仅仅是单个的数据,而是拥有某个相同键值的对象集合。例如下面的例子,我们有以下的数据:

牛逼的 reduce数据去重

首先我们来看看一个老生常谈的问题,我们假设有这样的一个对象:

const data = [{name: "Kris",age: "24"},{name: "Andy",age: "25"},{name: "Kitty",age: "25"},{name: "Andy",age: "25"},{name: "Kitty",age: "25"},{name: "Andy",age: "25"},{name: "Kitty",age: "25"}];

现在我们要去重里面name重复的对象,这时候我们可以利用reduce,例子如下:

const dataReducer = (prev, cur, idx) => {let obj = {};const { name } = cur;obj[name] = cur;return {...prev,...obj};};const reducedData = data.reduce(dataReducer, {});let newData = Object.values(reducedData);

批量生成对象元素

在鱼头的实际业务中,有一个操作是需要对类似以下的对象进行操作的:

{a1: 'data',a2: 'data',...,an: 'data'}

像我这么懒的鱼,肯定不会一个个手写,所以就有了以下方法

const createList = (item, idx) => {let obj = {};obj[`a${idx}`] = "data";return obj;};const listReducer = (acc, cur) => (!acc ? { ...cur } : { ...cur, ...acc });const obj = Array.from(new Array(20), createList).reduce(listReducer);

文章来源:陈大鱼头

小节

今天的内容就和大家分享到这里,感谢你的阅读。如果你喜欢我的分享,麻烦给个关注、点赞加转发哦,你的支持,就是我分享的动力,后续会持续分享代码片段,欢迎持续关注。

    推荐阅读
  • 家产剧情介绍(讲的是什么故事)

    处在社会中低层的三个兄弟厌倦着生活的鸡毛蒜皮,自然放不下自觉份内应得的家产。高老爷子的猝逝反给高家留下一道难解的谜题。与弟弟们的激烈争抢不同,性情平和的长女大秀无意争锋,但其子霍耀庭却因牵扯其中而无法坐视不理。正当遗产争夺战发展到白热化阶段的时候,一场飞来横祸突袭了高家。亲情在左,金钱在右,站在这个岔路口,高家人要何去何从。

  • 玛莎拉蒂古韵山西行(一路向西去大理)

    11月1日,2014玛莎拉蒂云南拉力之旅开启,这是时隔两年后玛莎拉蒂的又一次云滇之行。16位玛莎拉蒂车主汇聚大理,在为期8天、长约900公里的旅程中一路驰骋,途径沙溪、丽江、塔城,直抵香格里拉。公司注册资金5000万元,包含有双品牌销售展厅,以及双品牌售后维修中心。义乌博骏员工以饱满的热情,周到的服务迎接各位客户朋友的光临,将竭诚为您提供超越期待的购车及售后体验。

  • vivos9值得入手吗优缺点(还在纠结买不买)

    刚刚开售不到一周,vivoS9销量和口碑双双迎来开门红,这也从侧面印证了这款新旗舰非常受欢迎。据了解此次vivoS9的配色灵感来源于光色灵动的大自然,在色彩美学基础上加入时间维度,打造出光影流动、如画似卷的印象拾光、子夜蓝和朝露白三款配色。此次vivoS9采用4400万像素超清AF前置双摄,通过全新像素隔离技术使传感器感光能力提升12%,并首创微缝式双柔光灯,配合屏幕补光环全方位“造光”,突破极夜环境对自拍光线的限制。

  • 坦克世界td哪个系好用(坦克世界的术语)

    跟着小编一起来看一看吧!坦克世界td哪个系好用十级中最好的TD是F系,一是前面硬,二是三连发威力强。其次是268,虽然伤害不是最高了但是穿深足,机动性比704强。MT=Mediumtank:中型坦克,攻击力、防御力、机动性相对平衡的坦克;HT=Heavytank:重型坦克,重视防御力和火力;LT=Lighttank:轻型坦克,重视机动力和侦察能力;TD=Tankdestroyer:反坦克歼击车,牺牲自身其他性能换来了同级别最强的火力;SPG=Self-propelledgun:自行火炮。

  • 本田xrv自动挡1.5价格多少钱(现在本田xrv1.5t手动挡的价格多少)

    本田XRV自动变速器的油耗与手动变速器不同。事实上,自动变速器车辆操作不当也会增加自动变速器的故障概率,正确使用自动变速器不仅可以延长变速器的使用寿命,还可以降低油耗。自动挡汽车发生故障需要拖车时,最好先抬起驱动轮,再拖动。其实这是因为自动变速箱配备了空挡位启动开关,自动变速箱必须将挡位放在P挡或N挡才能启动,以免在其他挡位误启动时导致汽车跳向前。

  • 前车合法挑头后车追尾谁责任(前车违反交通规则造成后车追尾谁的责任)

    造成追尾的责任认定:。在前车正常驾驶情况下,后车因为车速过快、精神不集中等原因,冲上来造成追尾事故的。道路交通事故中,听到最多的事故就是汽车追尾,城市里经常出现两车追尾,而高速公路上更容易出现连环追尾现象。任何防止追尾的措施都是相对的,保持合理的车距才是预防追尾的根本,雨天和冰雪道路尤其重要。

  • 2022商丘中考最低录取分数线是多少 商丘2021年中考最低分数线

    商丘市教育局7月15日最新消息:2022年商丘中考全市最低录取分数控制线为272分,详情如下:

  • 新款吉利帝豪gs申报图(吉利新帝豪GS将上市)

    网上车市从吉利官方了解到,新帝豪GS现已全面到店并开启预售,推出动、雅两个造型,预售价为7.78-11.68万元,与现款车型的售价区间保持一致。新车最大的亮点是新增了1.4TCVT、1.5TD7DCT两种动力总成,并全部满足国六排放标准。新帝豪GS悬挂了吉利全新黑色LOGO,搭配熏黑色水滴涟漪运动式上格栅,整车造型更加个性、运动化。

  • 孙红雷王骏迪三亚(52岁孙红雷携妻出席活动)

    孙红雷带娇妻走红毯8月份,知名男星孙红雷,罕见携带娇妻王骏迪出席活动,并且一同走在了红毯之上。不得不说,孙红雷与娇妻的公开亮相,让人难忘。孙红雷与王骏迪之恋据悉,孙红雷出生于1970年的黑龙江,毕业于中戏的孙红雷,在圈内颇有知名度。经历过沧海桑田之后,孙红雷终于在2009年承认与小15岁女友王骏迪的恋情,恋爱5年后也终于结婚,婚后生了一个女儿。

  • 奔驰glc改装方向盘和液晶仪表(奔驰C级GLC改装触摸大屏无线carplay)

    在奔驰车型家族中,贯穿中控屏全液晶仪表盘几乎是奔驰内饰豪华的一大特征,然而C级和GLC的中控一直未得到被眷顾,即使是最新改款的glc也没能把贯穿屏配备上,这无疑是GLC车主最大的痛点,作为老款GLC车主注定与贯穿中控屏无缘C级glc最低配车型配备的屏幕为6.5英寸屏幕,高配的是8.4新款达到了10.2英寸,今天给大家带来的是老款奔驰GLC改装的10.2寸触摸大屏内置无线carplay手机互联原车的