wqjiao / points-issues Goto Github PK
View Code? Open in Web Editor NEW日常问题点的汇总
日常问题点的汇总
以前我们常用的是 <html lang="zh-CN">
或简写的 <html lang="zh">
,但实际上 W3 language tags 推荐使用 zh-Hans 简体中文
、zh-Hant 繁体中文
,可以提高一致性和准确。
1.声明文档使用的字符编码
<meta charset="utf-8">
用于 HTML5
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
用于 HTML4
或者 XHTML
或用于过时的 dom 解析器通常我们会使用短的。实际上,在 HTML5
中,以上两种是等价的,只是短的更容易被记住。更多对比见 stackoverflow
2.优先使用 IE 最新版本和 Chrome
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"/>
3.360 使用 Google Chrome Frame
<!-- 如果没有安装 GCF(Google Chrome Frame),使用最高版本的IE内核渲染 -->
<meta name="renderer" content="webkit" />
<meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1" />
具体详情见 360 浏览器内核控制
<!-- 强制使用webkit渲染 -->
<meta name="renderer" content="webkit">
<meta name="force-rendering" content="webkit">
4.百度禁止转码
在使用百度移动搜索时,百度会自动将网站进行转码,添加一些烦人的广告,如果我们不做百度广告,是可以通过 meta
标签禁止网站被转码
<meta http-equiv="Cache-Control" content="no-transform" />
<meta http-equiv="Cache-Control" content="no-siteapp" />
<!-- 表示页面同时适合在移动设备和PC上进行浏览 -->
<meta name="applicable-device" content="pc,mobile">
相关网站:
5.SEO 优化
<title>your title</title>
<meta name="keywords" content="your keywords">
<meta name="description" content="your description">
<meta name="author" content="author,email address">
<meta name="robots" content="index,follow">
6.为移动设备添加 viewport
,可以让布局在移动浏览器上显示的更好
<meta
name ="viewport"
content ="
width=device-width,
initial-scale=1.0,
maximum-scale=3.0,
minimum-scale=1.0,
user-scalable=no
"
>
width=device-width
会导致 iPhone5 添加到主屏后以 WebApp 全屏模式打开页面时出现黑边
注意: minimal-ui
iOS8 中已经删除
7.ios 设备
<meta name="apple-mobile-web-app-title" content="标题">
<meta name="apple-mobile-web-app-capable" content="yes"/>
<!-- 在 "apple-mobile-web-app-capable" content="yes" 时生效 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
default 默认值。
black 状态栏背景是黑色。
black-translucent 状态栏背景是黑色半透明。
如果设置为 default 或 black ,网页内容从状态栏底部开始。
如果设置为 black-translucent ,网页内容充满整个屏幕,顶部会被状态栏遮挡。
<meta name="format-detection" content="telephone=no" />
<!-- 电话号码、邮箱 -->
<meta name="format-detection" content="telephone=no,email=no" />
<meta
name="apple-itunes-app"
content="app-id=myAppStoreID, affiliate-data=myAffiliateData, app-argument=myURL"
>
content 属性可以传三个参数,以逗号隔开:
app-id(必选) 填写应用在APPStrore的ID
affiliate-data(可选) 是iTunes 分销联盟计划的ID 一般用不到。
app-argument(可选)点击『打开』给APP传参数
8.关闭 chrome 浏览器下翻译插件
<meta name="google" value="notranslate" />
9.去除手机半透明背景
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
meta
标签去除<meta name="msapplication-tap-highlight" content="no">
注意:部分机型可能去除不了,如果是按钮,可以避免使用 a
、input
,使用 div
代替
10.刷新浏览器
content -- 时间;网址
<meta http-equiv="Refresh" content="2;URL=http://www.baidu.com">
11.强制竖屏与全屏
landscape -- 横屏;portrait -- 竖屏
<!-- UC强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
12.应用模式
<!-- UC应用模式:默认全屏,禁止长按菜单,禁止手势,标准排版,强制图片显示 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- UC使用适屏模式显示 -->
<meta name="layoutmode" content="fitscreen">
<!-- UC强制图片显示 -->
<meta name="imagemode" content="force">
<!-- UC禁止夜间模式显示 enable|disable -->
<meta name="nightmode" content="disable">
<!-- UC当页面有太多文字时禁止缩放 -->
<meta name="wap-font-scale" content="no">
13.UC排版模式
UC 浏览器提供两种排版模式,分别是适屏模式(fitscreen)及标准模式(standard),其中适屏模式简化了一些页面的处理,使得页面内容更适合进行页面阅读、节省流量及响应更快,而标准模式则能按照标准规范对页面进行排版及渲染。
<meta name="layoutmode" content="fitscreen|standard">
14.cookie 设定指定时间后删除
<!-- Set-Cookie(cookie设定):如果网页过期,那么存盘的cookie将被删除 GMT格式 -->
<meta
http-equiv="Set-Cookie"
content="cookie value=xxx;expires=Friday,12-Jan-200118:18:18GMT;path=/"
>
Object.keys()
方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in
循环遍历该对象时返回的顺序一致 (两者的主要区别是 一个 for-in 循环还会枚举其原型链上的属性)。
let obj = {name: 'aaa', age: '20'}
Object.keys(obj); // ['name', 'age']
Object.values()
方法返回一个给定对象自己的所有可枚举属性值的数组,值的顺序与使用 for...in
循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )。
let obj = {name: 'aaa', age: '20'}
Object.keys(obj); // ['aaa', '20']
Object.entries()
方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用for...in
循环遍历该对象时返回的顺序一致(区别在于 for-in 循环也枚举原型链中的属性)
let obj = {name: 'aaa', age: '20'}
Object.keys(obj); // [['name', 'aaa'], ['age', 20']]
循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)
var obj = {'0': 'a', '1': 'b', '2': 'c'};
for (var i in obj) {
console.log(i, obj[i]);
}
返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性).
var obj = {'0': 'a', '1': 'b', '2': 'c'};
Object.getOwnPropertyNames(obj).forEach((key) => {
console.log(key, obj[key]);
});
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)
var obj = {'0': 'a', '1': 'b', '2': 'c'};
Object.keys(obj).forEach((key) => {
console.log(key, obj[key]);
});
返回一个数组,包含对象自身的所有属性,不管属性名是 Symbol 或字符串,也不管是否可枚举
var obj = {'0': 'a', '1': 'b', '2': 'c'};
Reflect.ownKeys(obj).forEach(function(key) {
console.log(key, obj[key]);
});
<div>
<img src="./img.jpg" width="100%" height="100%" />
</div>
div, img {
margin: 0;
padding: 0;
}
div {
width: 100%
}
div {
height: 250px;
}
div {
font-size: 0;
}
div {
line-height: 0;
}
img {
display: block;
}
理论上两者的用法及功能类似,但是也有区别, <Fragment>
可以绑定 key
,而 <>
不能,只能当做单纯的空标签使用,目前(v16.12.0
) key
是唯一可以传递给 Fragment
的属性。
参考 React 官网:https://zh-hans.reactjs.org/docs/fragments.html
arr.flat(depth)
depth
提取嵌套数组的结构深度,默认是 1let arr = [1, 2, [3, 4, [5, 6]]];
arr.flat(); // [1, 2, 3, 4, [5, 6]]
arr.flat(Infinity); // [1, 2, 3, 4, 5, 6]
reduce
、contat
递归多维数组降维let arr = [1, 2, [3, 4, [5, 6]]];
function flattenDeep(arr) {
return arr.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
}
flattenDeep(arr); // [1, 2, 3, 4, 5, 6]
要使 canvas 适配高倍屏,可以将 canvas 放大到设备像素比来绘制,最后将canvas压缩成一倍的物理大小来展示。
<canvas width="400" height="600" style="width: 200px;height: 300px;"></canvas>
相当于以下设置,ratio 放大倍数:
canvas.style.width = canvas.width + 'px';
canvas.style.height = canvas.height + 'px';
canvas.width = canvas.width * ratio;
canvas.height = canvas.height * ratio;
盒模型是有两种标准的,一个是标准模型,一个是IE模型
标准模型:只包含内容 content 的宽高
IE模型:盒模型的宽高是内容(content)+填充(padding)+边框(border)的总宽高
css 设置两种模型:
/* 标准模型 */
box-sizing:content-box;
/* IE模型 */
box-sizing:border-box;
function getType(obj) {
return Object.prototype.toString.call(obj).replace(/\[object (\w+)\]/, "$1");
}
function getType(obj) {
return Object.prototype.toString.call(array).slice(8, -1);
}
伪类选择器结合 transform
: scale
缩小一半;
viewport
结合 rem
<!-- devicePixelRatio=2 -->
<meta name="viewport" content="initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no">
<!-- devicePixelRatio=3 -->
<meta name="viewport" content="initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no">
background-image
.background-image-1px {
background: url(../img/line.png) repeat-x left bottom;
-webkit-background-size: 100% 1px;
background-size: 100% 1px;
}
border-image
.border-image-1px {
border-bottom: 1px solid #666;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2) {
.border-image-1px {
border-bottom: none;
border-width: 0 0 1px 0;
-webkit-border-image: url(../img/linenew.png) 0 0 2 0 stretch;
border-image: url(../img/linenew.png) 0 0 2 0 stretch;
}
}
类的方法默认不会自动绑定 this,在调用时如果忘记绑定 this,那么 this 的值将会是 undefined。
通常如果不是直接调用,应该为方法绑定 this。绑定方式有以下几种:
1、在 onClick 时使用匿名(箭头)函数绑定
<button onClick={() => this.handleClick()}>按钮</button>
<!-- 传参 -- 该方法 点击 时才会执行 -->
<button onClick={() => this.handleClick(data)}>按钮</button>
2、在 onClick 时使用 bind 绑定 this
Function.prototype.bind 来为事件处理函数传递参数
```
handleClick() {
alert('我点击了按钮');
}
...
按钮
<!-- 传参 -- 该方法 点击 时才会执行 -->
<button onClick={this.handleClick.bind(this)}>按钮</button>
```
3、在构造函数中使用 bind 绑定上下文
constructor(props) {
super(props);
this.handleClick = this.handleClick.bind(this);
}
...
handleClick() {
alert('我点击了按钮');
}
...
<button onClick={this.handleClick}>按钮</button>
<!-- 传参 -- 该方法在 render 时会直接被执行 -->
<button onClick={this.handleClick(data)}>按钮</button>
4、使用属性初始化器语法(箭头函数)绑定 onClick
handleClick = () => {
alert('我点击了按钮');
}
...
<button onClick={this.handleClick}>按钮</button>
<!-- 传参 -- 该方法在 render 时会直接被执行 -->
<button onClick={this.handleClick(data)}>按钮</button>
总结
方式1 和 方式2:
在 onClick 时绑定this,影响性能,且当方法作为属性传递给子组件的时候会引起重渲问题
优点:写法比较简单,当组件中没有 state 的时候就不需要添加类构造函数来绑定 this,传参 -- 该方法 点击 时才会执行
缺点:每一次调用的时候都会生成一个新的方法实例,因此对性能有影响,且当这个函数作为属性值传入低阶组件的时候,这些组件可能会进行额外的重新渲染,因为每一次都是新的方法实例作为的新的属性传递。
方式3:
在类构造函数中绑定 this,调用的时候不需要再绑定,官方推荐的绑定方式,性能最好的方式
优点:只会生成一个方法实例,并且绑定一次之后如果多次用到这个方法也不需要再绑定。
缺点:即使不用到 state,也需要添加类构造函数来绑定 this,代码量多。
方式4:
利用属性初始化语法,将方法初始化为箭头函数,因此在创建函数的时候就绑定了 this,最好的方式
优点:创建方法就绑定 this,不需要在类构造函数中绑定,调用的时候不需要再作绑定,结合了前三种方式的优点。
缺点:需要用 babel 转译
方式3 和 方式4:
共同缺点:传参 -- 该方法在 render 时会直接被执行
传参
向方法中传参时,使用 方法1 箭头函数(arrow functions) 和 方法2 bind(Function.prototype.bind)
事件对象 e 要放在最后 handleClick(data, e),作为第二个参数传递
通过箭头函数的方式,事件对象必须显式的进行传递,但是通过 bind 的方式,事件对象以及更多的参数将会被隐式的进行传递
let values = {create_time: '2019-12-10', name: 'wqjiao', ... };
方式一:声明一个对象存储空间,向对象中赋值
缺点:需要遍历;声明了一个多余的存储空间;对象中的值很多时,赋值操作过多;
// 1:遍历
let params = {};
Object.keys(values).map(item => {
if (item === 'create_time') {
params.createTime = item;
} else {
params = {
...params,
item,
}
}
// ...
});
// 2:直接赋值
let params = {
createTime: values.create_time,
name: values.name,
// ...
};
console.log(params);
方式二:简单粗暴 delete
values.createTime = values.create_time;
delete values.create_time;
console.log(values);
JSON.stringfy()
序列化替换const mapObj = {
created_time: 'createdTime'
};
JSON.parse(
JSON.stringify(values).replace(/created_time/gi, matched => mapObj[matched])
);
Obj.function.call(thisArg, ...argArray);
thisArg -- Context
...argArray -- 函数参数
let mathObj = {
pi: 3.14,
area: function(r) {
console.log(this); // this 指向上下文{pi: 3.14, area: ƒ, circumference: ƒ}
return this.pi * r * r;
},
circumference: function(r) {
return 2 * this.pi * r;
},
volume: function(r, h) {
return this.pi * r * r * h;
}
};
mathObj.area(2); // 12.56
// 但此时要求 pi 精确到小数点后 5 位,并立即执行该方法得出结果
mathObj.area.call({pi: 3.14159}, 2); // 12.56636
Obj.function.apply(thisArg, argArray)
thisArg -- Context
argArray -- 参数数组
上述代码也可以使用 apply()
,与 call()
类似,结果一致,只是参数的类型不一样
let mathObj = {
pi: 3.14,
area: function(r) {
console.log(this); // this 指向上下文{pi: 3.14, area: ƒ, circumference: ƒ}
return this.pi * r * r;
},
circumference: function(r) {
return 2 * this.pi * r;
},
volume: function(r, h) {
return this.pi * r * r * h;
}
};
mathObj.volume.call({pi: 3.14159}, 2, 6); // 参数作为函数参数被传递 75.39815999999999
mathObj.volume.apply({pi: 3.14159}, [2, 6]); // 函数参数作为数组传递 75.39815999999999
bind 将一个全新的 this 注入到指定的函数上,改变 this 的指向, 使用 bind 时,函数不会像 call 或 apply 立即执行
let mathObj = {
pi: 3.14,
area: function(r) {
console.log(this); // this 指向上下文{pi: 3.14, area: ƒ, circumference: ƒ}
return this.pi * r * r;
},
circumference: function(r) {
return 2 * this.pi * r;
},
volume: function(r, h) {
return this.pi * r * r * h;
}
};
let newVolume = mathObj.volume.bind({pi: 3.14159});
newVolume(2, 6);
它允许我们将上下文注入一个函数,该函数返回一个具有更新上下文的新函数。这意味着这个变量将是用户提供的变量,这在处理 JavaScript 事件时非常有用。
var button = document.getElementById("button"),
text = document.getElementById("text");
button.onclick = function() {
alert(this.id); // 弹出text
}.bind(text);
// 由于 IE6 - IE8 浏览器不支持,需要进行代码模拟
// 判断是否存在 bind 方法
if (!function() {}.bind) {
Function.prototype.bind = function(context) {
var self = this,
args = Array.prototype.slice.call(arguments);
return function() {
return self.apply(context, args.slice(1));
}
};
}
三种方式都是改变函数的 this 对象的指向;其中第一个参数都是 this 要指向的对象;都可以利用后续参数进行传参。但是 bind 返回对应函数,便于后续调用,而 apply、call 都是立即调用。
1.var 存在提升,我们能在声明之前使用。let、const 因为暂时性死区的原因,不能在声明前使用
2.var 在全局作用域下声明变量会导致变量挂载在 window 上,其他两者不会
3.let 和 const 作用基本一致,但是后者声明的变量不能再次赋值
4.let 只在当前作用域中有效(可以解决闭包存在的弊端),且在相同作用域中不能定义两个一样的变量
absolute && translate
.parent {
position: relative;
}
.son{
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
absolute
.parent {
position: relative;
}
.son{
position: absolute;
margin: auto;
width: 100px;
height: 50px;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
table && table-cell
.parent {
display: table;
width: 100%;
height: 50px;
}
.son {
display: table-cell;
vertical-align: middle;
}
.parent {
display: flex;
}
.son {
margin: auto;
}
或
.parent {
display: flex;
justify-content: center;
align-items: center;
}
或
.parent {
display: flex;
justify-content: center;
}
.son {
align-self: center;
}
.parent {
display: grid;
}
.son {
justify-self: center;
align-self: center;
}
.parent {
position: relative;
}
/* 无需知道被居中元素的宽高 */
.son {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
margin: auto;
}
str.split('').reverse().join('');
使用遍历
currentTarget 始终是指向事件绑定的元素(监听事件者);
target 指向用户触发的元素(真正发出者)。
div::-webkit-scrollbar {
width: 6px; /* 高宽分别对应横竖滚动条的尺寸 */
height: 1px;
}
/* 滚动条里面小方块 */
div::-webkit-scrollbar-thumb {
border-radius: 4px;
background: #999;
}
/* 滚动条里面轨道 */
div::-webkit-scrollbar-track {
border-radius: 4px;
background: #f2f2f2;
}
reg.exec(str)
一个在字符串中执行查找匹配的RegExp方法,它返回一个数组(未匹配到则返回null)。
/^(.*)\.(.+)$/.exec('hello.png'); // ['hello.png', 'hello', 'png']
reg.test(str)
一个在字符串中测试是否匹配的RegExp方法,它返回true或false。
/^(.*)\.(.+)$/.test('hello.png'); // true
str.match(reg)
一个在字符串中执行查找匹配的String方法,它返回一个数组或者在未匹配到时返回null。
'hello.png'.match(/^(.*)\.(.+)$/); // ['hello.png', 'hello', 'png']
str.search(reg)
一个在字符串中测试匹配的String方法,它返回匹配到的位置索引,或者在失败时返回-1。
'hello.png'.search(/^(.*)\.(.+)$/); // 0
str.replace(reg, str1)
一个在字符串中执行查找匹配的String方法,并且使用替换字符串替换掉匹配到的子字符串。
'hello.pn-g'.replace(/[^a-z.]/g, ''); // hello.png
str.split([separator[, limit]])
一个使用正则表达式或者一个固定字符串分隔一个字符串,并将分隔后的子字符串存储到数组中的String方法。
'hello.png'.split(/^(.*)\.(.+)$/); // ["", "hello", "png", ""]
input::-webkit-input-placeholder,
textarea::-webkit-input-placeholder {
color: #999;
}
input:-moz-placeholder,
textarea:-moz-placeholder {
color: #999;
}
input::-moz-placeholder,
textarea::-moz-placeholder {
color: #999;
}
input:-ms-input-placeholder,
textarea:-ms-input-placeholder {
color: #999;
}
rem
能够实现自适应布局的效果,用在移动端开发。它是相对于根元素 html
的 font-size
文字大小来变化的。它的原理简单的理解就是开发人员根据设计稿规定的宽度去设置一个比较合适的rem,通过媒体查询 @media
来设置不同设备屏幕宽度下 html
的 font-size
,从而实现自适应的效果。
event.preventDefault()
方法可防止元素的默认行为。如果在表单元素中使用,它将阻止其提交。如果在锚元素中使用,它将阻止其导航。如果在上下文菜单中使用,它将阻止其显示或显示。event.stopPropagation()
方法用于阻止捕获和冒泡阶段中当前事件的进一步传播。
const arr = [1, 2, 3, 4, 5];
const obj = { 1: 'a', 2: 'b', 3: 'c' }
const set = new Set([1, 2, 3, 4, 5])
obj.hasOwnProperty('1'); // true
obj.hasOwnProperty(1); // true
set.has('1'); // false
set.has(1); // true
使用 translate2d
出现模糊
因为元素的高度、宽度中有奇数, 使用 translate(-50%,-50%)
之后,相当于宽度、高度除以2的效果,会出现 0.5px。浏览器能分辨的最小像素为1px,因此出现了模糊。
所以,使用 translate(-50%,-50%)
的时候,一定要注意让元素的宽度、高度为偶数。
使用 translate3d
出现模糊
里面的值用固定参数而不是百分比,如 translate3d(50px,10px,10px)
, 则不会模糊。原因尚未明确。
1000000000..toLocaleString('de-DE')
'1000000000'.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
'1000000000'.replace(/(\d)(?=(\d{3})+\b)/g, '$1,')
用于输出普通信息
使用占位符 %c 自定义打印标题的样式,一眼看出自己打印的日志:
console.log("%c 车300", 'color: red; background: #000');
用于输出提示性信息
用于输出错误信息
用于输出警示信息
输出一组信息的开头
console.group
输出一组信息的结束
console.groupEnd
将表格数据显示为表格
对输入的表达式进行断言,只有表达式为false时,才输出相应的信息到控制台
统计代码被执行的次数
直接将该DOM结点以DOM树的结构进行输出,可以详细查对象的方法发展等等(比for in方便)
计时开始
console.time
计时结束
console.timeEnd
配合一起使用来查看CPU使用相关信息
在 Profiles 面板里面查看就可以看到 cpu 相关使用信息
配合一起记录一段时间轴
堆栈跟踪相关的调试
清除控制台
使用日志级别向控制台输出消息"debug"
将指定计时器的值记录到控制台。
在浏览器的时间轴或瀑布工具中添加标记
返回最近一次表达式执行的结果,功能跟按向上的方向键再回车是一样的
部分渲染树(或者整个渲染树)需要重新分析并且节点尺寸需要重新计算,表现为重新生成布局,重新排列元素
由于节点的几何属性发生改变或者由于样式发生改变,例如改变元素背景色时,屏幕上的部分内容需要更新,表现为某些元素的外观被改变
重绘
不一定 重排
,但 重排
一定会产生 重绘
。
var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i ++) {
console.log(i, arr[i]);
}
var arr = [1, 2, 3];
arr.forEach(function(val, index) {
console.log(val, index);
});
var arr = [1, 2, 3];
for (var i in arr) {
console.log(i, arr[i]);
}
不仅支持数组,还支持大多数类数组对象
也支持字符串遍历,它将字符串视为一系列的 Unicode 字符来进行遍历
var arr = [1, 2, 3];
for (var value of arr) {
console.log(value);
}
let arr = [{
id: 0,
text: 'a'
}, {
id: 1,
text: 'b'
}];
// map()/filer()
let str = arr.map( (item) => {
return [item.id]; // 字符串、数组、对象
});
宽松相等
const a = { value : 0 };
a.valueOf = function() {
return this.value += 1;
};
console.log(a == 1 && a == 2 && a == 3); // true
注意:
宽松相等 == 会先将左右两两边的值转化成相同的原始类型,然后再去比较他们是否相等。
在转化之后( == 一边或两边都需要转化),最后的相等匹配会像 === 符号一样去执行判断。
宽松相等是可逆的,对于任何值 A 与 B,通常 A == B 与 B == A 具有相同的表现(除了转换的顺序不同)。
ToPrimitive(input, PreferredType?)
可选参数 PreferredType 可以指定最终转化的类型,它可以是 Number 类型或 String 类型,
这依赖于 ToPrimitive() 方法执行的结果返回的是 Number 类型或 String 类型
严格相等
var value = 0; //window.value
Object.defineProperty(window, 'a', {
get: function() {
return this.value += 1;
}
});
console.log(a===1 && a===2 && a===3) // true
类型固定时,宽松相等 与 严格相等
var value = 0;
const a = {
get: function() {
return this.value += 1;
}
}
console.log((0, a.get)() == 1 && (0, a.get)() == 2 && (0, a.get)() == 3); // true
console.log((0, a.get)() === 1 && (0, a.get)() === 2 && (0, a.get)() === 3); // true
Object.defineProperty
语法
Object.defineProperty(obj, prop, descriptor)
参数
obj 用于定义属性的对象。
prop Symbol 要定义或修改的名称或属性。
descriptor 正在定义或修改属性的描述符。
返回值
传递给函数的对象
参考链接
```
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
```
```
overflow: hidden;
text-overflow: ellipsis;
text-overflow: ellipsis-lastline;
display: -webkit-box;
-webkit-line-clamp: 2; /*需要显示的行数*/
-webkit-box-orient: vertical;
border: 1px solid #ddd;
```
Array.flatMap()
flatMap()
方法对原数组的每个成员执行一个函数(相当于执行 Array.prototype.map()
),然后对返回值组成的数组执行 flat()
方法。该方法返回一个新数组,不改变原数组。
flatMap()
方法的参数是一个遍历函数,该函数可以接受三个参数,分别是当前数组成员、当前数组成员的位置(从零开始)、原数组。
arr.flatMap(function callback(currentValue[, index[, array]]) {
// ...
}[, thisArg])
Array.map()
Array.map()
方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
let arr = [1, 2, 3, 4];
arr.flatMap(x => x * 2); // [2, 4, 6, 8]
arr.map(x => x * 2); // [2, 4, 6, 8]
arr.flatMap(x => [x * 2]); // [2, 4, 6, 8]
arr.flatMap(x => [[x * 2]]); // [[2], [4], [6], [8]]
arr.map(x => [x * 2]); // [[2], [4], [6], [8]]
reduce
与 concat
做等价操作let arr1 = [1, 2, 3, 4];
arr1.flatMap(x => [x * 2]); // arr1.flatMap(x => x * 2); // [2, 4, 6, 8]
arr1.reduce((acc, x) => acc.concat([x * 2]), []); // [2, 4, 6, 8]
替换/删除/添加数,该方法会改变原始数组
splice(index, len, [item]);
index: 数组开始下标
len: 替换/删除的长度
item: 替换的值,删除操作的话 item 为空
let arr = ['a','b','c','d'];
// 删除起始下标为1,长度为1的一个值,len设置的1,如果为0,则数组不变
arr.splice(1, 1); // ['a','c','d']
// 删除起始下标为 1,长度为 2 的一个值,len 设置的 2
arr.splice(1, 2); // ['a','d']
let arr = ['a','b','c','d'];
// 替换起始下标为 1,长度为 1 的一个值为 ‘ttt’,len 设置的 1
arr.splice(1, 1, 'ttt'); // ['a','ttt','c','d']
// 替换起始下标为1,长度为2的两个值为‘ttt’,len设置的1
arr.splice(1, 2, 'ttt'); // ['a','ttt','d']
let arr = ['a','b','c','d'];
// 表示在下标为 1 处添加一项 ‘ttt’
arr.splice(1, 0, 'ttt'); // ['a','ttt','b','c','d']
let array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
array = array.slice(0, 4); // [0, 1, 2, 3]
slice()
可以接受负数,表示它将接受数组末尾的值
let arr = [1, 5, 8, 9,56];
console.log(arr.slice(-1)); // [56]
console.log(arr.slice(-2)); // [9, 56]
delete 删除掉数组中的元素后,会把该下标出的值置为undefined,数组的长度不会变,优势:原数组的索引也保持不变,此时再遍历数组元素,会跳过其中 undefined 的元素
let arr = ['a','b','c','d'];
for (index in arr) {
document.write('arr[' + index + ']='+arr[index]);
}
// 中间出现两个逗号,数组长度不变,有一项为 undefined
delete arr[1] //['a', ,'c','d']
event.defaultPrevented
用于判断事件的默认行为是否被取消event.preventDefault()
阻止事件默认行为获取 Canvas 绘制的图片时,报出错误信息:
Uncaught DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
。大致的意思是'被修改的画布不能被导出'。没有得到 CORS
(Cross-domain resource sharing) 权限,不过 stackoverflow 上已经有人给出了解决方法,使用 image.setAttribute("crossOrigin", 'Anonymous')
获得 CORS
权限。
let image = new Image();
// CORS 策略,会存在跨域问题 https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
image.setAttribute("crossOrigin", 'Anonymous'); // 允许跨域获取该图片
image.src = url;
image.onload = function () {
let canvas = document.createElement('canvas');
canvas.width = this.naturalWidth;
canvas.height = this.naturalHeight;
canvas.getContext('2d').drawImage(this, 0, 0);
// Data URI
resolve(canvas.toDataURL('image/png'));
};
// console.log(image.src);
image.onerror = () => {
reject(new Error('图片流异常'));
};
Number 转换成 String
'' + 1 => '1'
1.toString()
性能上来说:('' +) > String() > .toString() > new String()
String 转换成 Number
另外,可以使用 +
运算实现 boolean
类型转换成 number
:
+true; // 1
+false; // 0
最常用的是 parseInt(),其实 parseInt() 是用于将字符串转换成数字,而不是浮点数和整型之间的转换,可以使用 Math.ceil()、 Math.floor() 或者 Math.round()。
Math.ceil(num) 数值上取整
Math.floor(num) 数值下取整
Math.round(num) 数值四舍五入
let link = document.getElementById('favicon');
link.href = "https://xxx.com/loginLogo.png";
let str = "123abc456";
let i = 3;
str=str.Substring(0,i); // or str=str.Remove(i,str.Length-i);
str=str.Remove(0,i); // or str=str.Substring(i);
str=str.Substring(str.Length-i); // or str=str.Remove(0,str.Length-i);
str=str.Substring(0,str.Length-i); // or str=str.Remove(str.Length-i,i);
string str = "123abc456";
string a="abc";
Regex r = new Regex(a);
Match m = r.Match(str);
if (m.Success) {
//绿色部分与紫色部分取一种即可。
str=str.Replace(a,"");
Response.Write(str);
string str1, str2;
str1=str.Substring(0, m.Index);
str2=str.Substring(m.Index + a.Length, str.Length - a.Length - m.Index);
Response.Write(str1 + str2);
}
·str=str.Replace("abc","ABC");
string str="adcdef";
int indexStart = str.IndexOf("d");
int endIndex =str.IndexOf("e");
string toStr = str.SubString(indexStart, endIndex - indexStart);
str1.Substring(str1.LastIndexOf(",")+1)
iPhoneX中的安全区域全覆盖,在 meta 标签中添加 viewport-fit=cover
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
auto: 默认 viewprot-fit:contain; 页面内容显示在 safe area 内
cover: viewport-fit:cover,页面内容充满屏幕
当我们设置 viewport-fit:cover 时:设置如下
```css
body {
padding-top: constant(safe-area-inset-top); /* 为导航栏+状态栏的高度 88px */
padding-left: constant(safe-area-inset-left); /* 如果未竖屏时为0 */
padding-right: constant(safe-area-inset-right); /* 如果未竖屏时为0 */
padding-bottom: constant(safe-area-inset-bottom);/* 为底下圆弧的高度 34px */
}
```
select() 方法用于选取文本域中的内容
所有主流浏览器都支持 select() 方法
textObject.select()
选取文本域的内容:
<input type="text" id="copyText" value="需要复制的内容">
<button type="button" onClick="handleClick()">复制</button>
<script>
function handleClick() {
document.getElementById("copyText").select();
document.execCommand('copy');
}
</script>
substr(begin, length)
从指定位置 begin
取指定长度 length
的字符串
substring(begin, end)
截取最小值与最大值位置之间的字符串,不接受负数参数(负数直接转换成 0)
slice(begin, end)
提取指定 开始 到 结束 位置元素的新数组,参数为负数时,表示从最后一位开始
简单的说,函数 A 内部有一个函数 B,函数 B 可以访问到函数 A 中的变量,那么函数 B 就是闭包。
这是一个面试中常见的问题,循环内使用闭包:
function A() {
let a = 1
window.B = function() {
console.log(a)
}
}
A()
B() // 1
for (var i = 0; i < 4; i++) {
setTimeout(function() {
console.log(i);
});
}
// 4 4 4 4
for (let i = 0; i < 4; i++) {
setTimeout(function() {
console.log(i);
});
}
// 0 1 2 3
for (var i = 0; i < 4; i++) {
setTimeout(function(i_local) {
return function () {
console.log(i_local);
}
}(i))
}
// 0 1 2 3
因为 let i
的是区块变量,每个 i
只能存活到大括号结束,并不会把后面的 for
循环的 i
值赋给前面的 setTimeout
中的 i
;而 var i
则是局部变量,这个 i
的生命周期不受 for
循环的大括号限制;
-
一元负号运算符位于操作数前面,并转换操作数的符号
-'55' -> -55
-(-'55') -> 55
注意:一元负号会将数值变成负数,如果不想变成负数,需要在前面再添加一个 -
(注意运算符优先级)。
+
一元正号运算符位于其操作数前面,计算其操作数的数值,如果操作数不是一个数值,会尝试将其转换成一个数值。 尽管一元负号也能转换非数值类型,但是一元正号是转换其他对象到数值的最快方法,也是最推荐的做法,因为它不会对数值执行任何多余操作。它可以将字符串转换成整数和浮点数形式,也可以转换非字符串值 true,false 和 null。小数和十六进制格式字符串也可以转换成数值。负数形式字符串也可以转换成数值(对于十六进制不适用)。如果它不能解析一个值,则计算结果为 NaN。
+'55' -> 55
~~
~~
返回一个整数(~按位非运算)
~~'15' -> 15
let num1 = Number("Hello World"); //NaN
let num2 = Number(""); // 0
let num3 = Number("000011"); // 11
let num4 = Number(true); // 1
let num1 = parseFloat("1234blue"); // 1234
let num2 = parseFloat("0xA"); // 0
let num3 = parseFloat("0908.5"); // 908.5
let num4 = parseFloat("3.125e7"); // 31250000
~~
小数时,只保留整数部分
4.5 | 0 // 4
~~4.5 // 4
Math.floor(4.5) // 4
Math.ceil(4.5) // 5
~~-4.5 // -4
Math.floor(-4.5) // -5
Math.ceil(-4.5) // -4
var data = {};
var b = (JSON.stringify(data) == "{}");
alert(b); // true
注意: 忽略转换 undefined、function、Symbol 属性
JSON.stringify({[Symbol("key")]: "foo"}); // {}
var obj = {};
var b = function() {
for(var key in obj) {
return false;
}
return true;
}
alert(b()); // true
此方法是 jquery 将 2 方法 (for in) 进行封装,使用时需要依赖 jquery
var data = {};
var b = $.isEmptyObject(data);
alert(b); // true
获取到对象中的属性名,存到一个数组中,返回数组对象,我们可以通过判断数组的 length 来判断此对象是否为空
var data = {};
var arr = Object.getOwnPropertyNames(data);
alert(arr.length === 0); // true
注意:此方法不兼容 IE8
与 4 方法类似,是 ES6 的新方法, 返回值也是对象中属性名组成的数组
var data = {};
var arr = Object.keys(data);
alert(arr.length === 0); // true
清除 input 框在页面中输入之后产生的历史记录,将 autocomplete 中的默认值 on 改成 off 即可
requestAnimationFrame(() => {})
window.requestAnimationFrame()
告诉浏览器 -- 执行一个动画,并且要求浏览器在下一次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行
cancelAnimationFrame(requestID)
window.cancelAnimationFrame()
取消一个先前通过调用 window.requestAnimationFrame()
方法添加到计划中的动画帧请求。
requestID
指之前调用 window.requestAnimationFrame()
返回的ID
> 自动将数据发送给服务端
> 前端与服务端均可以对 cookies 进行增删改
> 存储数据大小:较小,不超过4k
> 时效性方面:可设置过期时间,否则长久保存
> 仅在当前网页关闭之前有效
> 存储大小:较大,可达 5M
> 时效性:会话级存储,关闭即消失
> 在所有同源窗口**享存储信息
> 存储大小:较大,可达 5M
> 时效性:除非手动清除,否则长久保存
都是保存在浏览器端,且是同源的。
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.