Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

随手记 | 前端吟游诗 #11

Open
WhiteYin opened this issue Jan 3, 2018 · 79 comments
Open

随手记 | 前端吟游诗 #11

WhiteYin opened this issue Jan 3, 2018 · 79 comments

Comments

@WhiteYin
Copy link
Owner

WhiteYin commented Jan 3, 2018

https://whiteyin.github.io/notes/

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 3, 2018

eslint-standard规范
这是一个以standard标准规范化js代码的工具,同时可以使用eslint设置该标准。比较方便易用。目前npm等网站都在使用。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 3, 2018

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 3, 2018

JavaScript 中的继承:ES3、ES5 和 ES6 - 天方夜谈
不同阶段JS规范下的对象继承实现方法,前两个问题在于原型链的传递方式。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 3, 2018

javascript 连等赋值问题
解析器在接受到 a = a.x = {n:2} 这样的语句后,会这样做:
找到 a 和 a.x 的指针。如果已有指针,那么不改变它。如果没有指针,即那个变量还没被申明,那么就创建它,指向 undefined。
a 是有指针的,指向 {n:1};a.x 是没有指针的,所以创建它,指向 undefined。
然后把上面找到的指针,都指向最右侧赋的那个值,即 {n:2}。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 4, 2018

JavaScript 运行机制详解:再谈Event Loop
JS事件处理机制是将同步任务放在事件栈中,异步任务放在事件队列里。当事件栈空,读取事件队列,将事件放入事件栈中,循环处理。定时任务在事件队列中,只有定时时间到才被处理。
setTimeout(fn,0)的含义是,指定某个任务在主线程最早可得的空闲时间执行,也就是说,尽可能早得执行。它在"任务队列"的尾部添加一个事件,因此要等到同步任务和"任务队列"现有的事件都处理完,才会得到执行。
HTML5标准规定了setTimeout()的第二个参数的最小值(最短间隔),不得低于4毫秒,如果低于这个值,就会自动增加。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 5, 2018

Pinterest的PWA实践
需求 :Pinterest 发现他们原来旧而慢的网络体验仅能将 1% 的用户转化为注册、登录或下载 app 作为本地应用使用的用户。为了提升转化率,它们开始投资PWA应用。
效果 :与旧移动端网页的体验相比,新移动端网页用户的使用时间增加了 40%,用户生成的广告收益增加了 44%,并且核心业务增长了 60%。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 5, 2018

let声明也会变量提升

  1. let 声明会提升到块顶部
  2. 从块顶部到该变量的初始化语句,这块区域叫做 TDZ(临时死区)
  3. 如果你在 TDZ 内使用该变量,JS 就会报错

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 5, 2018

关于let变量是否提升的讨论
getify对变量提升的定义是要同时具有2点:既要在运行前的编译阶段将声明与作用域绑定,又要能够在作用域中的任何位置获得对变量引用。var关键字声明的变量2点都满足,因此有变量提升;而let和const关键字声明的变量只满足第一点,因为临时死区的原因无法在任何位置时获得引用,因此没有变量提升。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 5, 2018

JS 判断CSS3 动画结束
监听animationend事件。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 5, 2018

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 8, 2018

CSS 布局方案
包括垂直居中、水平居中、多列定宽一列自适应、圣杯等布局。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 8, 2018

margin的百分比值是相对于包含块的宽度来定。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 8, 2018

创建层叠上下文的元素具有的特征

  1. 根元素 (HTML),
  2. z-index 值不为 "auto"的 绝对/相对定位,
  3. 一个 z-index 值不为 "auto"的 flex 项目 (flex item),即:父元素 display: flex|inline-flex,
  4. opacity 属性值小于 1 的元素(参考 the specification for opacity),
  5. transform 属性值不为 "none"的元素,
  6. mix-blend-mode 属性值不为 "normal"的元素,
  7. filter值不为“none”的元素,
  8. perspective值不为“none”的元素,
  9. isolation 属性被设置为 "isolate"的元素,
  10. position: fixed
  11. 在 will-change 中指定了任意 CSS 属性,即便你没有直接指定这些属性的值
  12. -webkit-overflow-scrolling 属性被设置 "touch"的元素

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 8, 2018

var a = [];
// 方法一
Object.prototype.toString.apply(a)==='[object Array]';
// 方法二
a.constructor === Array;

判断是否为数组。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 8, 2018

label的for属性值要与后面对应的input标签id属性值相同

<label for='Name'>Number:</label>
<input type=“ text “ name='Name' id='Name'/>

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 8, 2018

重构、回流

浏览器的重构指的是改变每个元素外观时所触发的浏览器行为,比如颜色,背景等样式发生了改变而进行的重新构造新外观的过程。重构不会引发页面的重新布局,不一定伴随着回流,回流指的是浏览器为了重新渲染页面的需要而进行的重新计算元素的几何大小和位置的,他的开销是非常大的,回流可以理解为渲染树需要重新进行计算,一般最好触发元素的重构,避免元素的回流。

比如通过通过添加类来添加css样式,而不是直接在DOM上设置,当需要操作某一块元素时候,最好使其脱离文档流,这样就不会引起回流了,比如设置position:absolute或者fixed,或者display:none,等操作结束后在显示。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 9, 2018

启动本地服务器:http-server

$ npm i --save-dev http-server
$ http-server

默认8080端口,使用-p 4000可以切换端口。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 9, 2018

剖析主流网站实现效果原理
包括知乎内容延时显示、导航栏动态底部、元素进入视口开始动画。

@WhiteYin
Copy link
Owner Author

今天遇到个小问题,css中的计算属性calc(100%-200px);语句是无效的,我原本以为是单位不同导致的。结果是因为-减号两边要加空格,写成calc(100% - 200px);
涨姿势了。

@WhiteYin
Copy link
Owner Author

JavaScript中,所有数字都是64位的浮点数,在某些运算中会将浮点数强制转换成32位的整数。

@WhiteYin
Copy link
Owner Author

parseInt()方法在转换数字为整数时会出现错误情况:

parseInt(10000000000000000.5);//1
parseInt(0.0000000000000003);//3

这是因为位数过多时会自动转成科学计数法相当于:

parseInt(1e+22);
parseInt(3e-16);

好像科学计数法在超过20位后parseInt把它当成字符串,识别到不是数字的e就结束了。

@WhiteYin
Copy link
Owner Author

JS原生的两种处理base64方法:
btoa():将一个base64编码过的字符串转换成ascii字符串或二进制数据,
atob():对 base64 编码过的字符串进行解码。
如果要转换的字符串中有中文,需要特殊处理:

function b64Encode(str) {
  return btoa(encodeURIComponent(str));
}

function b64Decode(str) {
  return decodeURIComponent(atob(str));
}

b64Encode('你好') // "JUU0JUJEJUEwJUU1JUE1JUJE"
b64Decode('JUU0JUJEJUEwJUU1JUE1JUJE') // "你好"

@WhiteYin
Copy link
Owner Author

JS 事件循环的一些细节
JS事件循环中最小延迟时间为1ms,并不是HTML规范定的4ms,规范受到了浏览器实现的影响。

@WhiteYin
Copy link
Owner Author

在安卓和IOS的原生应用中,字体大小往往不会随着设备屏幕大小的改变而改变。因此,现在移动端HTML页面中使用的rem单位并不是完美方案。在设计中应该尽量避免。
rem不是神农草
个人觉得应该多考虑细节,rem方案虽然简单但是细节处理并不好。至少在保持字体大小一致方面做的并不好。

@WhiteYin
Copy link
Owner Author

URLSearchParams
URLSearchParams API可以用来处理url中的查询字段,如果不支持可以使用第三方库。

@WhiteYin
Copy link
Owner Author

web storage API 在对sessionStorage或localStorage操作时会触发storage事件。当同时打开同一域名下的不同网页,其中一个网页修改storage时,其他网页会触发storage事件,而该页面不会。从某种程度上讲,可以实现多窗口通信。
storage事件的回调函数会有一个event对象,包括4个属性:

  1. key:发生变化的键名;
  2. oldValue:更新前的值。若该键是新增操作,则该值为null;
  3. newValue:更新后的值。若删除操作,该值为null;
  4. url:修改storage的网页url。

@WhiteYin
Copy link
Owner Author

根据大漠的博客,手机淘宝在移动端适配中使用的方案从flexible.js到vw再到viewport-units-buggyfill,可以看出适配需要处理的问题在于:

  1. 不同屏幕宽度下如何保证布局不变:rem或者vw;
  2. 视网膜屏中如何处理逻辑像素与物理像素不对应的问题:根据dpr修改meta;
  3. 1px如何处理:修改scale或者使用write svg插件。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Jan 25, 2018

思考为什么在移动端retina屏幕下,1px的边框会看上去是2px?

首先需要知道设备独立像素与屏幕物理像素的概念。
物理像素,指的是屏幕中的像素数。这个是我们前端开发无法控制的。
设备独立像素,有代表性的就是css中的像素单位。拿这个来举例,我们设置样式border:1px solid,这里的1px就是1独立像素。

从用户的视角来说,只能看到物理像素,并不能看到设备独立像素。在电脑或非retina屏幕下物理像素与独立像素是1:1的关系。但是在retina屏幕下,往往是2:1甚至是3:1的情况。这个比例我们用dpr(device pixel ratio)来表示。公式如下:
dpr = 物理像素 / 设备独立像素(适用于x或y轴方向)
这个公式,就像电阻的定义式一样,并不能说明dpr是由右侧两个变量决定。
举个例子,当手机的dpr为2时,一个css像素在屏幕上应该是2x2=4个物理像素,也就是宽是两倍,长也是两倍。

设置1px边框时,由于dpr=2,因此高度也就是粗细会显示成2px。这里的2px使用的是物理像素单位。

要解决这个问题,有两种方法:

  1. 手机淘宝的方案是根据dpr动态设置meta元素中的scale缩放为1/dpr;
  2. 最新的方法是使用postcss的插件:write svg来画出一条1px的细线。

@mythsman
Copy link

呀~难得看到老乡同行,加个友链互相学习喽~~

@WhiteYin
Copy link
Owner Author

@mythsman 没问题。
这个是你的博客吧?,我想想加在什么位置。

@WhiteYin
Copy link
Owner Author

今天看到个说法,JS的sort()方法在元素为22个时使用冒泡排序,在22个以上时使用快速排序。但是没有搜到相关文章,以后如果有面试题问到我就反问一下面试官吧。
由于sort()默认按字典序排序,所以在调用的时候要传入一个compare方法处理number从小到大排序。

@WhiteYin
Copy link
Owner Author

熟悉jQuery的前端开发经常会把函数写在$(document).ready()内部,以确保网页上的各个元素都可以用jQuery的选择器取到了。翻看jQuery的源码可以看到,$(document).raedy()其实触发时机是DOMContentLoaded和load事件中较早的那一个。不过由于DOMContentLoaded触发时间应该永远都在load之前,所以相当于jQuery的ready就等于是DOMContentLoaded。

DOMContentLoaded在HTML的DOM全部加载解析完成就会触发,此时你已经可以用css selector去查询到页面上的DOM元素了。而load事件需要等待页面上的样式表、图片、frame等元素全都加载完成才会触发。如果你希望通过js来获取页面上的元素样式并根据获取到的值做相应的改动,那这类js最好写在load事件的回调中。

@WhiteYin
Copy link
Owner Author

实现一个四分之一圆

<div></div>

div{
    height:100px;
    width:100px;
    border-top-left-radius:100%;
    background-color:blue;
}

实现一个半圆

div{
    height:50px;
    width:100px;
    background-color:blue;
    border-radius:50% 50% 0 0;
}

@WhiteYin
Copy link
Owner Author

this.state={
    a:0
}
this.setState({a:this.state.a+1});
this.setState({a:this.state.a+1});
this.setState({a:this.state.a+1});

实际上只增加了1,因为setState不是立即执行的,react会把多个setState合并然后统一执行。
setState在此之前不会更新state,所以三个setState中的this.state.a一直是0。
setState只会在两种情况下更新state:

  1. 更新生命周期中的render;
  2. shouldComponentUpdate返回false;

同时,setState不会触发componentReceiveProps周期。

@WhiteYin
Copy link
Owner Author

十进制转换成其他进制,可以使用辗转相除法,利用栈保存每次的余数直到商为0。

@WhiteYin
Copy link
Owner Author

严格模式主要有以下限制。

  • 变量必须声明后再使用
  • 函数的参数不能有同名属性,否则报错
  • 不能使用with语句
  • 不能对只读属性赋值,否则报错
  • 不能使用前缀 0 表示八进制数,否则报错
  • 不能删除不可删除的属性,否则报错
  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]
  • eval不会在它的外层作用域引入变量
  • eval和arguments不能被重新赋值
  • arguments不会自动反映函数参数的变化
  • 不能使用arguments.callee
  • 不能使用arguments.caller
  • 禁止this指向全局对象
  • 不能使用fn.caller和fn.arguments获取函数调用的堆栈
  • 增加了保留字(比如protected、static和interface)

重点记:

  1. 变量必须声明后再使用
  2. 函数的参数不能有同名属性,否则报错
  3. 不能使用前缀 0 表示八进制数,否则报错
  4. arguments不会自动反映函数参数的变化
  5. 不能使用caller和callee
  6. this指向不再默认为window,而是undefined

@WhiteYin
Copy link
Owner Author

隐藏select标签的下拉小箭头,可以设置下面的属性:

-webkit-appearance:none;

不同浏览器设置不同的前缀。

@WhiteYin
Copy link
Owner Author

图片如果使用img标签显示,当路径不正确时会使用浏览器默认图像,用户体验不好。
而使用background-image代替,能够保证在图片路径不正确时不会出现浏览器默认图像。可以看看SF主页右上角用户头像的写法。

@WhiteYin
Copy link
Owner Author

jQuery使用class或标签名查找节点可能返回一个数组,每一项为DOM对象,而不是jQuery对象。因此需要使用arr.eq(n)来获取arr中下标为n的数组项。不建议使用$(arr[n])来获取。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 2, 2018

删除windows系统中文件名过长的文件
今天从npm下载的一个模块中,有一个文件名非常长的json文件,直接删除会提示文件名过长无法操作。bing了以后发现上面链接中的方法,最终解决了。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 2, 2018

当对元素仅设置一边或两个相对边的border样式时,border默认为长方形。而一旦同时设置两条相邻边的border样式,这两条border会表现成直角三角形。再如果,设置三个相邻边的border样式后,中间的夹边会表现成梯形或等腰三角形,这与宽高是否为0有关。
基于这个特性,我们可以制作出直角三角形:

{
    border-top:10px solid transparent;
    border-left:10px solid yellow;
}

或者是等腰三角形:

{
    height:0;
    border-top:10px solid transparent;
    border-left:10px solid yellow;
    border-bottom:10px solid transparent;
}

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 2, 2018

在发布到 npm 之前,你可以将你的模块 link 到全局从而测试你的可分享设置模块。像这样:

npm link

随后,在你的项目中使用你的可分享配置模块,像这样:

npm link eslint-config-myconfig

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 2, 2018

使用扩展运算符:

{...state}

需要安装babel-preset-stage-3

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 2, 2018

在React 15.5版本后,使用proptypes进行类型检查,需要从prop-types模块中导入。

import PropTypes from 'prop-types';

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 4, 2018

在 JavaScript 中避免使用 eval() 被认为是一个很好的实践。这么做是考虑到安全性和性能的影响,这也是为什么很多检查工具(包括 ESLint )推荐禁用 eval()。然而,也有一些其它方式,通过传递一个字符串,并将它解析为 JavaScript 代码,也有类似的问题。

首当其冲的就是 setTimeout()、setInterval() 或者 execScript() (仅限IE浏览器),它们都可以接受一个 JavaScript 字符串代码作为第一个参数。

在链接地址中使用 javascript: 被有些人认为是 eval 的一种形式。在 javascript: 链接中的代码必须由浏览器解析和赋值,其处理方式与 eval 一样。

@WhiteYin
Copy link
Owner Author

WhiteYin commented Apr 9, 2018

遇到一个问题:

var obj = {
    a:function (){
        _this = this;
        function b(){
            console.log(this);
            console.log(_this);
        }
	b();
	return b;
    }
}
obj.a();//输出a和window
obj.a()();//输出a和window两次

问题不在于输出多少次。只是不清楚b函数中this的指向。
我一开始以为this能受闭包作用,就算有4种调用方式也能让子作用域保留上层作用域的this指向。但实际上没有关系,也不应该有关系。因为如果子作用域的this是上层作用域的this,那么还怎么调用自己作用域内的变量呢……我真是糊涂了。

顺带也复习一下this的四种指向吧。
一般this的指向与函数调用的方式有关,目前是四种:

  1. 直接调用:非严格模式下this指向window对象,严格模式下为undefined;
  2. 构造函数调用:与new操作符联用时,this指向目标对象;
  3. 方法调用:作为对象的方法调用时,this指向该对象;
  4. 绑定调用:apply、call和bind指向指定的this。

之所以不说箭头函数,是因为箭头函数严格来说没有this。

@WhiteYin
Copy link
Owner Author

为了在 React 组件中编写注释,我们必须将其作为 JavaScript 中的多行注释放在括号中。
形如:{/* this is a comment */}

@WhiteYin
Copy link
Owner Author

// 开始的a标签数量为1
const getAByQuerySelector = document.querySelectorAll('a');
const getAByJquery = $('a');
const getAByJS = document.getElementsByTagName('a');
// 添加一个a标签
const node = document.createElement('a');
document.documentElement.append(node);
// 检查是否发生变化
// 1,无变化
console.log(getAByQuerySelector);
// 1,无变化
console.log(getAByJquery);
// 2,自动加一
console.log(getAByJS);

@WhiteYin
Copy link
Owner Author

WhiteYin commented May 9, 2018

HTML中,script标签如果设置了defer属性,相当于将这个标签放在了body标签之后,等到渲染完毕后才执行。
而如果设置了async属性,则相当于将这个标签从文档顶部动态向底部移动,这个标签的前面是已经渲染好的内容,后面是还未渲染的内容。一旦浏览器下载完这个js文件,则停止移动,此时会加载并执行该js文件。

@WhiteYin
Copy link
Owner Author

core-js 是babel-polyfill 的底层依赖,通过各种奇技淫巧,用 ES3 实现了大部分的 ES2017 原生标准库,同时还要严格遵循规范。

@WhiteYin
Copy link
Owner Author

IE8 不支持console方法

@WhiteYin
Copy link
Owner Author

今天在看堆糖的商店页面,发现一种实现正方形div的方法:设置宽度和padding-bottom为相同的百分比值,并且显式设置height为0。原理就是padding的百分比是相对于父元素来计算的。

此外,我还发现一个以前没注意过的特性:当元素高度为0、padding不为0并且overflow为hidden时,其子元素仍会显示高度为padding值的一部分。也就是说,子元素渲染其实是从border-box的左上角开始,到其右下角。并不是我以前认为的content-box。

@WhiteYin
Copy link
Owner Author

IE8浏览器中,不能动态修改input的type属性。

@WhiteYin
Copy link
Owner Author

想要将26个字母与相应的顺位数字对应,可以使用charCodeAt方法。

let letterCode = 'a'.charCodeAt() - 97;// 0
letterCode = 'b'.charCodeAt() - 97;// 1

@WhiteYin
Copy link
Owner Author

git pull <remote-name> <branch-name>

将远程仓库的最新版本拉取到本地分支。

选项:

  1. --allow-unrelated-histories:将两个没有相关历史的仓库合并。比如你在github上建立了一个仓库,编辑了一些内容。然后又在本地有一个仓库,编辑了一些内容。当你pull时会被告知fatal: refusing to merge unrelated histories。这时,加上这个选项就可以了。

@WhiteYin
Copy link
Owner Author

windows下tree命令
tree a -l 2 --ignore 'node_modules,build'

http://sunshiyong.com/2018/05/13/tree-win/#tree-cli%E7%9A%84%E4%BD%BF%E7%94%A8

@WhiteYin
Copy link
Owner Author

WhiteYin commented Mar 23, 2021

问题场景:使用了Websocket的项目,切换tab页后频繁断开连接。

chrome会限制后台页面JS的计时器触发间隔,导致心跳计时发送间隔过长,服务端(?)判断失活,断开连接。
image

更新:
可以使用hacktimer代替解决

@WhiteYin
Copy link
Owner Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants