# 网站
# 好的学习资源:
《重新介绍 JavaScript》 (opens new window)—— Mozilla 出品的JS 教程
微软面向初学者的网络开发课程 (opens new window)
TypeScript 入门教程 - xcatliu (opens new window)
# 好的工具及速查手册:
Web 技术参考 - Mozilla官网权威参考手册
caniuse.com (opens new window) - JS、CSS等API浏览器兼容性检查
冴羽的博客 (opens new window) - JavaScript深入系列、ES6系列、React系列 26.2Kstar
50多个使用HTML、CSS和JS的迷你web项目 (opens new window) - 11.7K
千古前端图文教程 (opens new window) - 18.7K star
被删的前端博客 (opens new window) - 1.7K star
# 博客
您可能希望使用的10个鲜为人知的 Web api (opens new window)
ESLint vs. Prettier 对于 JavaScript 来说,最好的代码格式化库是什么?https://betterprogramming.pub/eslint-vs-prettier-57882d0fec1d
重构之路:webpack打包体积优化(超详细) (juejin.cn) (opens new window)
ECMAScript 2016 到 2019 的所有新功能 (opens new window) www.v2ex.com/t/635647
# 基本数据类型
# Number
//1到6之间的随机数 https://stackoverflow.com/a/4960020
Math.floor(Math.random() * 6) + 1
function randomIntFromInterval(min, max) { // min and max included
return Math.floor(Math.random() * (max - min + 1) + min);
}
# Map
Object.fromEntries(aMap))
# 字符串处理
# startsWith
//确定一个字符串是否以另一个字符串开头。这个方法区分大小写。
//语法:其中 position 可选,在 str 中搜索 searchString 的开始位置,默认值为 0。
//如果在字符串的开头找到了给定的字符则返回true;否则返回false。
str.startsWith(searchString[, position])
const str1 = 'Saturday night plans';
console.log(str1.startsWith('Sat'));
// expected output: true
console.log(str1.startsWith('Sat', 3));
// expected output: false
# 相等比较
相等比较最好用===
If you know they are strings, then there's no need to check for type.
如果您知道它们是字符串,那么就不需要检查类型。
"a" == "b"
However, note that string objects will not be equal.
但是,请注意字符串对象不会相等。
new String("a") == new String("a") //will return false.
Call the valueOf() method to convert it to a primitive for String objects,
调用 valueOf ()方法将其转换为 String 对象的原语,
new String("a").valueOf() == new String("a").valueOf()// will return true
//对象转字符串
var str = JSON.stringify(jsObj);
//字符串转对象
var obj = JSON.parse(str);
//----------字符串替换----------
var str = "1\n2\n3\n";
//将字母\n替换成分号
str = str.replace("\n",";");
//结果:1;2\n3\n 只替换了第一个
str = str.replace(/\n/g, ";");
//结果:1;2;3; replace 的第一个参数可以是正则表达式,/g标识是全文匹配(全局替换)
//----------字符串包含----------
//字符串stringA 是否包含字符串 stringB
stringA.includes(stringB)
var testDivs = Array.prototype.filter.call(testElements,function(testElement){
return testElement.nodeName === 'DIV';
});
//base64编码解码
aaa = window.btoa('12345678')
window.atob(aaa)
# 字符的 Unicode 表示法
"\u0061"
// "a"
//超出\u0000~\uFFFF之间的字符:
"\uD842\uDFB7"
// "𠮷"
"\u20BB7"
// " 7"
"\u{20BB7}"
// "𠮷"
"\u{41}\u{42}\u{43}"
// "ABC"
let hello = 123;
hell\u{6F} // 123
'\u{1F680}' === '\uD83D\uDE80'
// true
# 循环字符串里的每个字符(ES6)
for (let codePoint of 'foo') {
console.log(codePoint)
}
// "f"
// "o"
// "o"
# 正则篇
//去掉开头结尾的某个同样字符
pathname = "/share/video/6736813535613013260/"
location.pathname.replace(/^\/|\/$/g, '')
//输出:"share/video/6736813535613013260"
const regex = /prefix[0-9a-zA-Z]{1,20}/g;
var currentURL = decodeURIComponent(window.location.href);
var result = currentURL.match(regex)
# 全部替换
我们知道 string.replace ()函数只替换第一个匹配项。 可以通过在正则表达式的结尾添加/g 来替换所有匹配项
var example = "potato potato";
console.log(example.replace(/pot/, "tom"));
// "tomato potato"
console.log(example.replace(/pot/g, "tom"));
// "tomato tomato"
# URL
How to get the value from the GET parameters? 如何从GET请求获取参数值? https://stackoverflow.com/a/979995/4493393
var url_string = "http://www.example.com/t.html?a=1&b=3&c=m2-m3-m4-m5"; //window.location.href
var url = new URL(url_string);
var c = url.searchParams.get("c");
console.log(c);
# 数组Array
let fruits = ['Apple', 'Banana']
console.log(fruits.length)
// 2
let first = fruits[0]
// Apple
//last object最后一个
let last = fruits[fruits.length - 1]
// Banana
fruits.forEach(function(item, index, array) {
console.log(item, index)
})
// Apple 0
// Banana 1
let newLength = fruits.push('Orange')
// ["Apple", "Banana", "Orange"]
let last = fruits.pop() // remove Orange (from the end)
// ["Apple", "Banana"]
//最后一个对象
console.log('last', [1, 3, 4, 5].slice(-1));//[5]
//最后一个对象
[1, 3, 4, 5].pop()
//最后5个对象
yourArray.slice(Math.max(arr.length - 5, 1))
//删除第一个对象,返回一个新的数组对象(原数组不改变)
yourArray.shift()
//删除第一个的对象,原数组改变
yourArray.splice(0, 1)
console.log('second_to_last', [1, 3, 4, 5].slice(-2));
//concat() 合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组
const array1 = ['a', 'b', 'c'];
const array2 = ['d', 'e', 'f'];
const array3 = array1.concat(array2);
console.log(array3);
//输出: Array ["a", "b", "c", "d", "e", "f"]
# 遍历
//遍历怎么break
[1, 2, 3].some(function(el) {
console.log(el);
return el === 2;//break的情况(条件)
});
//ECMAScript2015 (aka ES6)
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (let el of arr) {
console.log(el);
if (el === 5) {
break;
}
}
[1,2,3].every(function(el) {
return !(el === 1);
});
//ES6
[1,2,3].every( el => el !== 1 )
# 包含
const pets = ['cat', 'dog', 'bat'];
console.log(pets.includes('cat'));
// expected output: true
# 提取唯一的值(去重)
We can create a new array only with the unique values by using the Set object and the Spread operator.
var entries = [1, 2, 2, 3, 4, 5, 6, 6, 7, 7, 8, 4, 2, 1]
var unique_entries = [...new Set(entries)];
console.log(unique_entries);
// [1, 2, 3, 4, 5, 6, 7, 8]
# 数组元素洗牌
Every day I'm shufflin'
var my_list = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(my_list.sort(function() {
return Math.random() - 0.5
}));
// [4, 8, 2, 9, 1, 3, 6, 5, 7]
# 合并多维数组
Simply by using the Spread operator.
var entries = [1, [2, 5], [6, 7], 9];
var flat_entries = [].concat(...entries);
// [1, 2, 5, 6, 7, 9]
# 使用长度调整数组的大小/清空数组
如果我们想调整数组的大小,只需重写数组的长度:
var entries = [1, 2, 3, 4, 5, 6, 7];
console.log(entries.length);
// 7
entries.length = 4;
console.log(entries.length);
// 4
console.log(entries);
// [1, 2, 3, 4]
# 对象
obj.constructor
获取类型
var myArray = [1,2,3];
(myArray.constructor == Array); // true
2
//对象有没有值
var hasData = !!aObject;
//https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty
//hasOwnProperty() 方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。
const object1 = {};
object1.property1 = 42;
console.log(object1.hasOwnProperty('property1'));
// expected output: true
console.log(object1.hasOwnProperty('toString'));
// expected output: false
console.log(object1.hasOwnProperty('hasOwnProperty'));
// expected output: false
防止对象是undefined
//node_modules/@vuepress/theme-default/util/index.js
headers = headers.map(h => Object.assign({}, h))
# 动态属性名
I always thought that I first had to declare an object before being able to assign a dynamic property.
const dynamic = 'flavour';
var item = {
name: 'Coke',
[dynamic]: 'Cherry'
}
console.log(item);
// { name: "Coke", flavour: "Cherry" }
# 类型判断
Array.isArray(obj)
obj instanceof Array
if(Object.prototype.toString.call(someVar) === '[object Array]') {
alert('Array!');
}
if(typeof someVar === 'string') {
someVar = [someVar];
}
if (somevar.constructor.name == "Array") {
// do something
}
# 类型转换
# number to string
We just have to use the concatenation operator with an empty set of quotation marks.
var converted_number = 5 + "";
console.log(converted_number);
// 5
console.log(typeof converted_number);
// string
# string to number
All we need is the + operator.
Be careful with this one since it only works with 'string numbers'.
the_string = "123";
console.log(+the_string);
// 123
the_string = "hello";
console.log(+the_string);
// NaN
# 时间
//时间戳(毫秒)
let timestamp = +new Date();
let timestamp2 = Date.now();
//Date类型获取time stamp
your_date.getTime()
定时刷新
<script type="text/javascript">
function myrefresh() {
window.location.reload();
}
setTimeout('myrefresh()', 9000);
</script>
//根据id获取元素
document.getElementById("YOUR_ID").innerHTML = "YOUR_CONTENT";
var $markdownElem = document.querySelector('#markdown');
//对象转字符串 JS打印对象
var str = JSON.stringify(jsObj);
//修改a标签的href属性
document.getElementById("abc").href="baidu.com";
//---------------字符串---------------
//最后几个字符 last few char
var lastFiveChars = "abcdefg".substr(-5);
str.substring(str.length - 1);
var lastLetter = str.charAt(str.length - 1)
str.slice(-1);
//字符串转对象
var str1 = JSON.parse(str);
//在JavaScript中创建多行字符串
var html = `
<div>
<span>Some HTML here</span>
</div>
`;
var str = "1\n2\n3\n";
//将字母\n替换成分号
str = str.replace("\n",";");
//结果:1;2\n3\n 只替换了第一个
str = str.replace(/\n/g, ";");
//结果:1;2;3; replace 的第一个参数可以是正则表达式,/g标识全文匹配
//根据class获取元素
var testElements = document.getElementsByClassName("btn");
var testDivs = Array.prototype.filter.call(testElements,function(testElement){
return testElement.nodeName === 'DIV';
});
//获取iframe 元素
document.getElementById("hongbaoframe").contentWindow.document.getElementById("aaa")
base64编码解码
aaa = window.btoa('12345678')
window.atob(aaa)
chrome 日本制作的一支创意广告,用一次关闭 300 个窗口创作了一支暖心的别样定格动画。
http://www.wandoujia.com/eyepetizer/detail.html?vid=3324
for(var i = 0; i < 337; i++){window.open('http://www.google.co.jp/landing/motto/tabplay/' + i + '.jpg');}
document.getElementById('post-2199').style.background="#EEEEEE";
<div class="entry-content" style="background:#EEEEEE; color:#111111">
//改变所有div的背景色
var x=document.getElementsByTagName("div");
for (var i = 0;i < x.length;i ++) {
var a = x[i];
a.style.background="#ddeedd";
}
//改变body背景色
document.body.bgColor='#cccccc'
# 语法
语句和声明
语句和声明 - JavaScript | MDN (mozilla.org) (opens new window)
# export
在创建JavaScript模块时,export 语句用于从模块(js文件)中导出实时绑定的函数、对象或原始值,以便其他程序可以通过 import 语句使用它们。
存在两种 exports 导出方式:
- 命名导出(每个模块包含任意数量)
- 默认导出(每个模块包含一个)
// 导出单个特性,let可以换成 var, const
export let name1, name2, …, nameN; // also var, const
export let name1 = …, name2 = …, …, nameN; // also var, const
export function FunctionName(){...}
export class ClassName {...}
// 导出列表(多个)
export { name1, name2, …, nameN };
// 重命名导出
export { variable1 as name1, variable2 as name2, …, nameN };
// 解构导出并重命名
export const { name1, name2: bar } = o;
// 默认导出
export default expression;
export default function (…) { … } // also class, function*
export default function name1(…) { … } // also class, function*
export { name1 as default, … };
// 导出模块合集
export * from …; // does not set the default export
export * as name1 from …; // Draft ECMAScript® 2O21
export { name1, name2, …, nameN } from …;
export { import1 as name1, import2 as name2, …, nameN } from …;
export { default } from …;
建议: 避免混合默认导出和命名导出
https://exploringjs.com/es6/ch_modules.html#sec_overview-modules
I generally recommend to keep the two kinds of exporting separate: per module, either only have a default export or only have named exports.
// Tips:默认导出实际上只是一个具有特殊名称 default 的命名导出。也就是说,以下两种说法是等价的:
import { default as foo } from 'lib';
import foo from 'lib';
//类似地,以下两个模块具有相同的默认导出:
//------ module1.js ------
export default function foo() {} // function declaration!
//------ module2.js ------
function foo() {}
export { foo as default };
import 多次是否是同一个实例?
使用export let的时候是的
https://stackoverflow.com/a/57050195/4493393
同一文件的所有导入都将引用内存中的相同对象:https://stackoverflow.com/a/48763053/4493393
// File: yolo.js
class Yolo {}
export let yolo = new Yolo();
// File: laser.js
import { yolo } from "./yolo.js";
// yolo is a single instance of Yolo class
// File: cat.js
import { yolo } from "./yolo.js";
// same yolo as in laster.js
# function函数
# 箭头函数
// 成功的回调函数
function successCallback(result) {
console.log("音频文件创建成功: " + result);
}
// 失败的回调函数
function failureCallback(error) {
console.log("音频文件创建失败: " + error);
}
function createAudioFileAsync(yesyes, nono, cc) {
console.log("异步创建音频文件")
return { then: console.log }
}
function audioSettings() {
console.log("音频设置")
}
function saySomething() {
console.log("saySomething wakaka")
}
// createAudioFileAsync(audioSettings, successCallback, failureCallback)
// const promise = createAudioFileAsync(audioSettings);
// promise.then(successCallback, failureCallback);
createAudioFileAsync(audioSettings).then(successCallback, failureCallback);
//箭头函数,https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions
// 用 Promise 来封装setTimeout方法
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
//使用
wait(2000).then(() => saySomething("到家了")).catch(failureCallback);
// 还原箭头函数
// 当箭头函数的函数体只有一个 `return` 语句时,可以省略 `return` 关键字和方法体的花括号,变成上面👆
const wait2 = ms => new Promise(function(resolve) {
setTimeout(resolve, ms)
});
// 当箭头函数只有一个参数时,可以省略参数的圆括号,变成上面👆
const wait3 = ms => {
return new Promise(function(resolve) {
setTimeout(resolve, ms)
})
};
// 下面的普通函数可以改写成如下的箭头函数
const wait4 = (ms) => {
return new Promise(function(resolve) {
setTimeout(resolve, ms)
})
};
const wait5 = function(ms) {
return new Promise(function(resolve) {
setTimeout(resolve, ms)
})
};
const wait22 = ms => new Promise(function(resolve, reject) {
if (ms > 10000) {
console.log("测试,时间太长了");
reject("时间太长了")
} else {
setTimeout(resolve, ms)
}
});
wait5(2000).then(() => saySomething("10 seconds")).catch(failureCallback);
# setTimeout
setTimeout(function () {
//do something
}, 800);
setTimeout(() => {
//do something
}, 1000);
# 元素
获取iframe元素的元素
window.document.getElementById('subsite').contentWindow.document.getElementById('app').__vue__
# 异常处理
try {
//你写的可能出现异常的代码
parseSupported = parse("01") !== 1;
} catch (exception) {
}
# 良好习惯
# 美化代码
https://prettier.io/docs/en/cli.html
命令行美化语法:
prettier [options] [file/dir/glob ...]
例子
# 要运行本地安装的(即当前文件夹的)Prettier版本,请在命令前添加npx
npx prettier --write src/router/iframePage.vue
# git commit前自动格式化
https://prettier.io/docs/en/precommit.html
npx mrm lint-staged
# 缩短条件之少用if
Short Circuit Conditionals
Let's take this example:
if (available) {
addToCart();
}
And shorten it by simply using the variable together with the function:
available && addToCart()
# 中高级
# 函数
# 默认参数值
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5, 2));
// expected output: 10
console.log(multiply(5));
// expected output: 5
# Promise
function buyTomatoes(sth) {
console.log("买菜:",sth)
const promise = new Promise(function(resolve, reject){
if (sth === "tomato") {
let obj = {msg:"success 买对菜了,可以进行下一步",code:200}
resolve(obj);
} else {
reject(new Error("panda error 哎,买错了"));
}
});
return promise;
}
function cooking(sth) {
console.log("做饭:",sth)
}
//不需要buyTomatoes返回的结果
buyTomatoes("tomato").then(cooking("番茄炒蛋")).catch(function(pppres) {
console.log("买错菜了",pppres)
})
//需要buyTomatoes返回的结果
buyTomatoes("tomato").then(ppres=> {
console.log("买对菜了",ppres)
}).catch(function(pppres) {
console.log("买错菜了",pppres)
})
buyTomatoes("potato").then(ppres=> {
console.log("买对菜了",ppres)
}).catch(function(pppres) {
console.log("买错菜了",pppres)
})
# Apply
使用率10% 难度40% 便利80%
// 用apply完成以避免循环,你可以
var array = ['a', 'b'];
var elements = [0, 1, 2];
array.push.apply(array, elements);
console.info(array); // ["a", "b", 0, 1, 2]
//而不必:
/*
for (var i = 0; i < elements.length; i++) {
array.push(elements[i]);
}
*/
修改Date new方法
//修复Safari new Date("2021-07-19 15:54:43") 返回Invalid Date的问题
Date = (function (Date) {
MyDate.prototype = Date.prototype;
// 将Date构造器的属性方法,复制到MyDate构造器上
var propertys = Object.getOwnPropertyNames(Date.prototype.constructor);
if (propertys && propertys.length > 0) {
for (var i = 0; i < propertys.length; i++) {
var name = propertys[i];
MyDate[name] = Date.prototype.constructor[name];
}
}
return MyDate;
function MyDate() {
// 当只有一个参数并且参数类型是字符串时,把字符串中的-替换为/
if (arguments.length === 1) {
let arg = arguments[0];
if (
Object.prototype.toString.call(arg) === "[object String]" &&
arg.indexOf("T") === -1
) {
arguments[0] = arg.replace(/-/g, "/");
}
}
let bind = Function.bind;
let unbind = bind.bind(bind);
return new (unbind(Date, null).apply(null, arguments))();
}
})(Date);
# import
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import#%E5%8A%A8%E6%80%81import
import("../tool/pplog.js").then((module) => {
// Do something with the module.
console.log("modulemodulemodule", module.default.panda);
});
# ESLint
./node_modules/eslint-loader/index.js error 'xxx' is defined but never used
Disabling a rule on a line or entirely on your project
https://stackoverflow.com/a/61875095
# JQuery
# event.stopPropagation()用法
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.5.1/jquery.min.js"></script>
</head>
<body onclick="MyBodyClick()">
<div onclick="MyClickOut()">
<div onclick="MyClickInner()">
<span id="MySpan">
I love JQuery!!
</span>
</div>
</div>
</body>
<script type="text/javascript">
function MyClickOut() {
alert("outer Div");
}
function MyClickInner() {
alert("Inner Div");
}
function MyBodyClick() {
alert("Body Click");
}
$(function () {
$("#MySpan").bind("click", function (event) {
alert("I'm span");
//表面意思是停止传播,效果是点击最上层的元素,只有最上层的元素响应点击事件
event.stopPropagation();
})})
</script>
</html>
# 元素
//获取iframe 元素
document.getElementById("xiaosongweb").contentWindow.document.getElementById("aaa")
//父获取子iframe
window.document.getElementById('subsite').contentWindow.document.getElementById('app').__vue__.globalVar.baseURL
//
document.getElementById("app").__vue__
//根据id获取元素
document.getElementById(id)
//根据class获取元素
document.getElementsByClassName("btn");
var list = document.getElementsByClassName("events");
for (let item of list) {
console.log(item.id);
}
var list= document.getElementsByClassName("events");
[].forEach.call(list, function(el) {
console.log(el.id);
});
chrome 日本制作的一支创意广告,用一次关闭 300 个窗口创作了一支暖心的别样定格动画。
http://www.wandoujia.com/eyepetizer/detail.html?vid=3324
for(var i = 0; i < 337; i++){window.open('http://www.google.co.jp/landing/motto/tabplay/' + i + '.jpg');}
document.getElementById('post-2199').style.background="#EEEEEE";
<div class="entry-content" style="background:#EEEEEE; color:#111111">
//改变所有div的背景色
var x=document.getElementsByTagName("div");
for (var i = 0;i < x.length;i ++) {
var a = x[i];
a.style.background="#ddeedd";
}
//改变body背景色
document.body.bgColor='#cccccc'
###event.stopPropagation();用法
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<script type="text/javascript" src="https://cdn.bootcss.com/jquery/1.5.1/jquery.min.js"></script>
</head>
<body onclick="MyBodyClick()">
<div onclick="MyClickOut()">
<div onclick="MyClickInner()">
<span id="MySpan">
I love JQuery!!
</span>
</div>
</div>
</body>
<script type="text/javascript">
function MyClickOut() {
alert("outer Div");
}
function MyClickInner() {
alert("Inner Div");
}
function MyBodyClick() {
alert("Body Click");
}
$(function () {
$("#MySpan").bind("click", function (event) {
alert("I'm span");
event.stopPropagation();
})})
</script>
</html>
Undefined 测试
var aaa = undefined
console.log('----'+aaa+'----'+typeof(aaa));
var bbb = 'undefined'
console.log('----'+bbb+'----'+typeof(bbb));
var ccc ;
console.log('----'+ccc+'----'+typeof(ccc));
if(aaa == 'undefined') {
console.log('666666');
}
if(aaa == undefined) {
console.log('777777');
}
# npm及JS库
https://bennettfeely.com/ztext/ 这个 JS 库可以将任何字体变成 3D 效果,支持中文。
HTML+CSS+JS在同一个窗口 https://tryenlight.github.io/demo/code-editor-project/index.html https://flems.io/
Code Playgrounds
https://jsfiddle.net/ http://codepen.io/ http://jsbin.com/
UI https://chakra-ui.com/docs/form/button
https://github.com/cowboy/javascript-hooker
# npm
#查看是谁依赖了browserify-sign
npm ls browserify-sign
npm-check (opens new window)是用来检查npm依赖包是否有更新,错误以及不在使用的,我们也可以使用npm-check进行包的更新。
全局安装npm-check:
$ npm install -g npm-check
/usr/local/bin/npm-check -> /usr/local/lib/node_modules/npm-check/bin/cli.js
- 检查npm包的状态:
npm-check -u -g
# 小技巧
# Chrome调试技巧
查看某元素所有CSS样式:右键审查元素然后选择Computed
选项卡
# 显示所有元素边界
var style = document.querySelector('#_outline_');
if (style) {
style.parentNode.removeChild(style);
} else {
style = document.createElement('style');
style.id = '_outline_';
style.innerHTML = "*{outline: 1px solid red}";
document.body.appendChild(style);
}