文章摘要moonshot-v1-8k
Standby API Responsing..
JavaScript 速记
日常记录一些 js/css 相对实用的小笔记,本笔记保持长期更新,如有错误或更好的方案留言反馈
使用 toString()
取随机字符串(toString 最大值为 32)
var rs=(num)=>{let rs=Math.random().toString(num);return rs.substring(2,rs.length)}
rs(2); //1011111100100110111101101110010000011101101001100001
rs(16); //40a52a10becc
使用 link()
创建指定参数链接
"example string".link("http://www.w3school.com.cn"); //<a href="http://www.w3school.com.cn">example string</a>"
使用 !+"v1"
判断 IE8 以下的浏览器
!+"\v1"; //true(IE8及以下)
!+"\v1"; //false(谷歌浏览器和IE9及以上)
使用原生js选择 不包含特定 class
的元素(How to Select Element That Does Not have Specific Class)
<ul id="tasks"> <li class="completed selected">One Task</li> <li>Two Task</li> </ul>
// select li which doesn't have a 'class' attribute... console.log(document.querySelector("li:not([class])")) // select li which doesn't have a '.completed' and a '.selected' class... console.log(document.querySelector("li:not(.completed):not(.selected)"))
通过创建 input
并使用 document.execCommand("copy")
复制文本框内容(注意这里不能隐藏文本框否则获取不到值)
var text="some sample text", //文本内容
copyIpt=document.createElement("input"); //创建文本框
//copyIpt.style.display="none";copyIpt.type="hidden";
document.body.appendChild(copyIpt); //添加文本框
copyIpt.value=text; //复制到文本框
copyIpt.select(); //选中所有文本
document.execCommand("copy") //复制所选内容
js内容选中即复制
document.onclick = function() {
if (window.getSelection) {
text = window.getSelection();
} else if (document.selection) {
text = document.selection.createRange();
}
// 放到粘贴板里,操作浏览器自身的API
// console.log(text.toString());
document.execCommand('Copy'); // 执行浏览器的复制命令
}
(更新精准/模糊匹配)js 正则匹配指定开头结尾内字符串(这里匹配 img
标签)
var str = "img: <img src='#' />",
filter = str.match(/\<img.*?\>/g); //<img src='#' />
var str = "img: <img src='#' />",
inclouds = str.match(/\<([\s\S]*?)\>/)[0], //<img src='#' />
notincloud = str.match(/\<([\s\S]*?)\>/)[1]; //img src='#' /
js 删除符合指定条件的数组对象中的某个对象
var arr = [{name:"a",age:1},{name:"b",age:2},{name:"c",age:3}];
console.log(arr) //a:1 b:2 c:3
for(let i=0;i<arr.length;i++){
arr[i].name=="b" ? arr.splice(i,1) : false;
}
console.log(arr) //a:1 c:3
js 函数参数执行 js 方法
var arr = ["a","b","c"],
forArr = forFunc=(arr,exe)=>{
if(arr!=null && arr!=undefined)
for(let i=0;i<arr.length;i++){
exe!=undefined ? exe(i) : false;
}
};
forFunc(arr,function(i){
console.log(arr[i]) //a,b,c
})
js 批量定义变量
var arr = ["a","b","c"],
for (let i=0; i<arr.length;i++) {
eval('var' +arr[i]+ '= document.getElementById("' +arr[i]+ '");');
}
console.log(a); //确保 id 为 a 的元素不等于 null 或 undefined
js Object.keys
用法举例
var arr = ["a","b","c"],
obj = {"a":"aaa","b":"bbb","c":"ccc"},
str = "String";
Object.keys(arr); //["0","1","2"]
Object.keys(obj); //["a","b","c"]
Object.keys(str); //["0","1","2","3","4","5"]
JavaScript 异步方案 async/await
const f = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(123);
}, 2000);
});
};
const testAsync = async () => {
const t = await f();
console.log(t);
};
testAsync();
//首先定义了一个函数 f,这个函数返回一个 Promise,并且会延时 2 秒,resolve 并且传入值 123。
//testAsync 函数在定义时使用了关键字 async,然后函数体中配合使用了 await,最后执行 testAsync。
//整个程序会在 2 秒后输出 123,也就是说 testAsync 中常量 t 取得了 f 中 resolve 的值,并且通过 await 阻塞了后面代码的执行,直到 f 这个异步函数执行完。
js 移除 string 中的空格
var str = "s triing",
str = str.replace(/\s+/g,""); //去除所有空格
去除两头空格:
str = str.replace(/^\s+|\s+$/g,""); //去除左空格
str = str.replace( /^\s*/, ''); //去除右空格
js 移除指定数组中的某一项
var arr = ["a","b","c"];
let index = arr.indexOf("b");
arr.splice(index,1);
console.log(arr) //["a","c"]
js 防抖(连续点击)
function debounce(fn, wait) {
var timeout = null;
return function() {
if(timeout !== null) clearTimeout(timeout);
timeout = setTimeout(fn, wait);
}
}
// 处理函数
function handle() {
console.log("handled 1000ms")
}
// 执行事件
window.addEventListener('click', debounce(handle, 1000));
var check;
window.onclick=()=>{
check ? clearTimeout(check) : check;
check = setTimeout(function(){
console.log('checked');
}, 1000);
}
js 自执行函数
(function a(){
console.log('auto_run_fn') //auto_run_fn(无需调用直接执行)
})()
js 自执行函数 this
指向
(function(){
console.log(this); //this 指向 window
var that = this; //that 指向 window
return (function(){
return this
})()
})();
JavaScript 闭包计数器
function closure(){
var counter = 0;
plus = function(){
counter++
};
subs = function(){
counter--
};
//闭包函数
return function(){
console.log(counter)
}
};
var res = closure(), //调用闭包函数
counter_plus = function(){
plus();
res()
},
counter_subs = function(){
subs();
res()
};
counter_plus(); //counter = 1
counter_subs(); //counter = 0
JavaScript 防抖(闭包)
function debounce(delay){
var timer = null;
return function(){
timer ? clearTimeout(timer) : timer;
timer = setTimeout(function(){
console.log("连续点击时,仅执行一次(最后一次)点击事件")
},delay)
}
};
var res = debounce(1000);
window.addEventListener('click',res) //连续点击时,仅执行一次(最后一次)点击事件
JavaScript 节流(闭包)
function throttle(delay){
var timer = null,
handle = function(){
console.log("连续点击时,每隔 1000ms 执行一次 handle()");
};
return function(){
if(timer==null){ //!timer
timer = setTimeout(function(){
//handle.apply(this,null); //apply 传递 argument 上下文 this 环境
handle();
timer = null //消除定时器表示激活
},delay)
}
}
};
var res = throttle(1000);
window.onclick=function(){
res() //连续点击时,每隔 1000ms 执行一次 handle()
}
JavaScript call()
与 apply()
console.log(this); //window
//call()、apply()、bind() 都是用来重定义 this 这个对象的!
var name="name",
age=0;
var obj={
name: "NAME",
objAge: this.age,
fn: function(arg){
console.log(this);
console.log("arg: "+arg);
}
},
newObj={
name: "Named",
age: 1
};
obj.fn(); //{NAME,0}
obj.fn.call(newObj,'string'); //{Named,1},"string"
obj.fn.apply(newObj,['array']); //{Named,1},[array]
obj.fn.bind(newObj,'string')(); //{Named,1},"string"
obj.fn.bind(newObj,['array'])(); //{Named,1},[array]
JS正则限制只能输入数字、或带小数点的数字,并且小数后面限制多少位
const length = 2
const reg = new RegExp(`^\\d+(\\.\\d{1,${length}})?$`)
JS 利用 offsetParent
判断元素是否可见
var p = document.querySelectorAll("p");
p.offsetParent!=null ? console.log("可见") : console.log("不可见");
JS 利用 split()
与 join()
实现 replaceAll()
的两种方式
var str = "[dog]man[cat]",
replace = ["[","]"],
all = ["【","】"],
obj = {
"[":"【",
"]":"】"
},
replaceAll = function(str,replace,all){
for(let i=0;i<replace.length;i++){
str = str.split(replace[i]).join(all[i])
};
return str
},
replaceObj = function(str,obj){
for(key in obj){
str = str.split(key).join(obj[key])
};
return str
};
replaceAll(str,replace,all); //"【dog】man【cat】"
replaceObj(str,obj); //"【dog】man【cat】"
Js 过滤字符串数字和非数字
var str="a1b2c3";
console.log(str.replace(/[0-9]/ig,"")); //abc
console.log(str.replace(/[^0-9]/ig,"")); //123
Js 获取指定父元素
function eachParent(curPar,tarPar){
while(curPar && curPar.nodeName.toLowerCase()!=tarPar){
curPar = curPar.parentNode
};
return curPar
}
Js 在 head 执行时当所有 dom 加载完成后再执行
var headfn = function(){
console.log("hellow world")
},
isloaded = function(){
window.addEventListener("DOMContentLoaded", headfn, false);
}
Js 滚动到当前滚动条底部
var focusScroll = function(focusarea){
focusarea.focus();
focusarea.scrollTop = focusarea.scrollHeight
};
focusScroll(textarea) //textarea 聚焦元素
Js textarea/input 值操作
var textarea = documen.getElementById("textarea")
selection = window.getSelection ? window.getSelection() : document.selection.createRange().text,
indexOfSelectBefore = textarea.selectionStart,
indexOfSelectAfter = textarea.selectionEnd;
textarea.setSelectionRange(0, 0); //定位光标到指定位置(不选中)
console.log(selection.toString()); //当前已选中文本
console.log(indexOfSelectBefore); //当前已选中文本前索引
console.log(indexOfSelectAfter); //当前已选中文本后索引
Js 使用 dispatchEvent 触发自定义事件
var event = new Event('click');
window.addEventListener('click',function(e){
console.log(1)
});
window.dispatchEvent(event) //log 1 without click the window
Js 获取最近一个月(上个月的今天至今为止)的 leancloud 标准日期格式
console.log(new Date()); //Tue Apr 27 2021 11:05:51 GMT+0800 (中国标准时间)
dateFormat = function(d){
const addZero = (n,m) => {
return n<m ? '0'+n : n;
},
year = d.getFullYear(),
month = p ? addZero(d.getMonth()+1,10) : addZero(d.getMonth(),10),
day = addZero(d.getDate(),10),
hour = d.getHours(),
minute = addZero(d.getMinutes(),10);
return year+ '-' +month+ '-' +day+' '+hour+':'+minute+':'+second;
};
dateFormat(new Date(),true); //2021-04-27 11:05:51
dateFormat(new Date(),false); //2021-03-27 11:05:51
Js 获取当前元素到窗口顶部/侧面距离
var el = document.getElementById("el");
console.log(el.getBoundingClientRect().top) //distance between el and window-top
获取 JS 数组中的相同元素的名称和数量
var ary =["anime","comic","game","movie","tv","anime"]; var res = []; ary.sort(); for(var i = 0;i<ary.length;){ var count = 0; for(var j=i;j<ary.length;j++){ if(ary[i] == ary[j]){ count++; } }; res.push([ary[i],count]); i+=count; } //res 二维数维中保存了 值和值的重复数 for(var i = 0 ;i<res.length;i++){ console.log("值:"+res[i][0]+" 重复次数:"+res[i][1]+"); }
// 不用reduce时: var arr = ["apple","orange","apple","orange","pear","orange"]; function getWordCnt(){ var obj = {}; for(var i= 0, l = arr.length; i<l; i++){ var item = arr[i]; obj[item] = (obj[item] +1 ) || 1; } return obj; } console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1} // 用reduce时: var arr = ["apple","orange","apple","orange","pear","orange"]; function getWordCnt(){ return arr.reduce(function(prev,next){ prev[next] = (prev[next] + 1) || 1; return prev; },{}); } console.log(getWordCnt());//{apple: 2, orange: 3, pear: 1}
Js 简单委托事件
<div id="atag">
<a>111</a>
<a>222</a>
</div>
const atag = document.querySelector("#atag");
atag.onclick=(e)=>{
var e = e || window.event,
t = e.target || e.srcElement,
p = "a"; //事件标签
// 创建 while 循环,直到 t=p,否则循环向上遍历 t 的 parentNode 是否为 p
while(t!=atag && t!=null){
if(t.nodeName.toLowerCase()==p){
console.log("delegated a tag");
break; //跳出循环
}else{
t = t.parentNode;
}
}
}
Js 在 iframe 中查找父页面变量或函数
var variable = "parentvar";
<iframe>
console.log(parent.variable) //parentvar
</iframe>
Js 利用访问 iframe 父页面变量
var parVar = "this var from parent"; //注意!不能使用 const 否则 iframe 不可读父页面变量
//iframe 页面内调用
console.log(parent.parVar) //"this var from parent"
Js 利用 postMessage 方法在 iframe 中与父页面跨域通信
<iframe id="postMessage"></iframe>
//子页面传数据至父页面同理 const person = { name: "name", age: 1 }; window.onload = function(){ document.getElementById("postMessage").contentWindow.postMessage(JSON.stringify(person),"/") //postMessage 第二参数可限制访问来源 }; //iframe 页面内调用 window.addEventListener("message",function(e){ let res = JSON.parse(e.data); //return parsed JSON Object alert(`getMessage ${res} from ${e.origin}`); //getMessage [Object Object] from / console.log(res) //{name: "name",age: 1} });
正则匹配指定标签内所有内容
<tag>[\w\W]*?</tag>
短路运算符 && || (除了NaN、null、””、undefined、0、function这几个为false外,其他皆为true)
false ? false : true
console.log(false&&true) //false (find true one by one)
console.log(false||true) //true (find true between both)
JS 鼠标拖拽时被中断
event.preventDefault() //阻止默认事件
element.setCapture() //捕获事件 element.releaseCapture() //释放事件
js 时间戳转为日期格式
function getLocalTime(nS) {
return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' ');
}
console.log(getLocalTime(1293072805)); //2010/12/23 上午10:53
JS阻止事件冒泡
e=e || window.event,
//阻止事件冒泡
//不仅仅要stopPropagation,还要preventDefault
pauseEvent = function(e){
if(e.stopPropagation) e.stopPropagation();
if(e.preventDefault) e.preventDefault();
e.cancelBubble=true;
e.returnValue=false;
return false;
}
js 获取指定 css 值(transform),不指定即返回所有匹配值
_getComputedStyle = function(element,property,which) {
const st = window.getComputedStyle(element, null),
tr = st.getPropertyValue('-webkit-'+property) ||
st.getPropertyValue('-moz-'+property) ||
st.getPropertyValue('-ms-'+property) ||
st.getPropertyValue('-o-'+property) ||
st.getPropertyValue(property) || 'FAIL';
if (tr === 'FAIL') {
return '';
};
if(which){
let target = tr.split(",")[which];
if(target){
return Number(target)
}else{
return 0
}
}else{
return tr
}
}
safari 父元素 overflow 子元素 transform 导致父元素 border-radius 失效
.father{
border-radius: 10px;
overflow: hidden;
transform: rotate(0deg); //仅需在设置 border-radius 的元素上添加 rotate(0deg) 即可修复
}
.child{
transform: translate(10px,10px)
}
调用 call 改变调用函数 this 指向,并调用其对象成员
var obj = {
name: 'andy',
age: 10,
sex: 'boy'
};
function func(a, b) {
console.log(this);
console.log(a + b);
};
function cons(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.desc = 'my name is '+name+', i am a '+age+' years old '+sex;
return this
};
function use(n, a, s){
cons.call(this, n, a, s)
}
func(1, 2); // return 3 (Window Object)
func.call(obj, obj.age, 2); // return 12 (obj Object)
cons(obj.name, obj.age, obj.sex); // Window Object
cons.call(obj, obj.name, obj.age, obj.sex); // obj Object
var usage = new use('刘德华', 18, '男');
console.log(usage);
apply 改变 this 数组参数
var o = {
name: 'andy',
};
function fn(arr) {
console.log(this);
console.log(arr); // 'pink'
}
fn.apply(o, ['pink']);
// 1. 也是调用函数 第二个可以改变函数内部的this指向
// 2. 但是他的参数必须是数组(伪数组)
// 3. apply 的主要应用 比如说我们可以利用 apply 借助于数学内置对象求数组最大值
// Math.max();
var arr = [1, 66, 3, 99, 4];
var arr1 = ['red', 'pink'];
// var max = Math.max.apply(null, arr);
var max = Math.max.apply(Math, arr);
var min = Math.min.apply(Math, arr);
console.log(max, min);
按照一定的模式,从数组或对象中提取值,将提取出来的值赋值给另外的变量
let ary = [1, 2, 3];
let [a, b, c, d] = ary;
console.log(a);
console.log(b);
console.log(c);
console.log(d); // undefined
let person = { name: 'lisi', age: 30, sex: '男' };
let { name, age, sex } = person;
console.log(name);
console.log(age);
console.log(sex);
let { name: myName } = person;
console.log(myName);
ES6 箭头函数 this 指向
var age = 100;
var obj = {
age: 20,
say: () => {
console.log(this.age); // Window
},
says: function(){
console.log(this.age); // obj
}
};
obj.say(); // 100
obj.says(); // 20
将一个不定数量的参数表示为一个数组
const sum = (...args) => {
let total = 0;
args.forEach((item) => (total += item));
return total;
};
console.log(sum(10, 20)); // 30
console.log(sum(10, 20, 30)); // 60
// 解构 ...args
let ary1 = [1, 2, 3];
let [s1, ...s2] = ary1;
console.log(s1); // 1
console.log(s2); // [2,3]
扩展运算符应用于数组合并
let ary1 = [1, 2, 3];
let ary2 = [4, 5, 6];
// ...ary1 // 1, 2, 3
// ...ary1 // 4, 5, 6
let ary3 = [...ary1, ...ary2];
console.log(ary3); // [1,2,3,4,5,6]
ary1.push(...ary2);
console.log(ary1); // [1,2,3,4,5,6]
利用扩展运算符将伪数组转换为真正的数组
<div>1</div>
<div>2</div>
<div>3</div>
<script>
var oDivs = document.getElementsByTagName('div');
console.log(oDivs);
var ary = [...oDivs];
ary.push('a');
console.log(ary);
</script>
找出第一个符合条件的数组成员,如果没有找到返回 undefined
var ary = [
{
id: 1,
name: '张三',
},
{
id: 2,
name: '李四',
},
];
let target = ary.find((item) => item.id >= 2);
console.log(target); // {id: 2, name: '李四'}
找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let ary = [10, 20, 50];
let index = ary.findIndex((item) => item > 15);
console.log(index);
某个数组是否包含给定的值,返回布尔值
let ary = ['a', 'b', 'c'];
let result = ary.includes('a');
console.log(result); // true
result = ary.includes('e');
console.log(result); // false
startsWith() 和 endsWith()
let str = 'Hello ECMAScript 2015';
console.log(str.startsWith('Hello')); // true
console.log(str.endsWith('2016')); // false
闭包案例
// 2. 利用闭包的方式得到当前小li 的索引号
for (var i = 0; i < lis.length; i++) {
(function (i) {
lis[i].onclick = function () {
console.log(i);
};
})(i);
}
// 闭包应用-3秒钟之后,打印所有li元素的内容
var lis = document.querySelector('.nav').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
(function (i) {
setTimeout(function () {
console.log(lis[i].innerHTML);
}, 3000);
})(i);
}
// 打车起步价13(3公里内), 之后每多一公里增加 5块钱. 用户输入公里数就可以计算打车价格
// 如果有拥堵情况,总价格多收取10块钱拥堵费
// function fn() {};
// fn();
var car = (function () {
var start = 13; // 起步价 局部变量
var total = 0; // 总价 局部变量
return {
// 正常的总价
price: function (n) {
if (n <= 3) {
total = start;
} else {
total = start + (n - 3) * 5;
}
return total;
},
// 拥堵之后的费用
yd: function (flag) {
return flag ? total + 10 : total;
},
};
})();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33
//闭包隐藏数据
function createCache(){
const data = {} //隐藏闭包中的数据不被外界访问
return {
set:function(key,val){
data[key] = val
},
get:function(key){
return data[key]
}
}
}
const c = createCache()
c.set('a',100)
console.log(c.get('a')) //100
// 闭包执行一次函数
function closure_once(fn,data){
let flag = false;
return function(){
if(!flag){
flag=true;
if(data){
return fn.call(this,...arguments)
}else{
fn.call(this,...arguments);
}
}
}
}
function sum(a,b){
console.log(a+b);
}
function sum_data(a,b){
return a+b;
}
let sum_once = closure_once(sum),
sum_once_data = closure_once(sum,true);
sum_once(1,2); // 3
sum_once(1,2); // ..
sum_once_data(1,2); // return 3
sum_once_data(1,2); // ..
//闭包事件绑定
function makeSizer(size) {
return function() {
document.body.style.fontSize = size + 'px';
};
}
var size12 = makeSizer(12);
var size14 = makeSizer(14);
var size16 = makeSizer(16);
document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
递归函数(函数内部调用函数自身,满足条件循环调用)
//求 1 * 2 * 3 ... * n 阶乘
function fn(n) {
if (n == 1) {
return 1;
} else {
return n * fn(n - 1);
}
}
console.log(fn(3));
console.log(fn(4));
// 根据 id 返回对应的数据对象..
js正则括号
// 中括号 字符集合.匹配方括号中的任意字符.
var reg = /^[abc]$/;
// a 也可以 b 也可以 c 可以 a ||b || c
// 大括号 量词符. 里面表示重复次数
var reg = /^abc{3}$/; // 它只是让c重复三次 abccc
console.log(reg.test('abc'));
console.log(reg.test('abcabcabc'));
console.log(reg.test('abccc')); // true
// 小括号 表示优先级
var reg = /^(abc){3}$/; // 它是让abc重复三次
console.log(reg.test('abc'));
console.log(reg.test('abcabcabc')); // true
console.log(reg.test('abccc'));
CLASS 类的基础构造方法
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
say() {
console.log(this.name + '你好');
}
}
var ldh = new Person('刘德华', 18);
ldh.say();
CLASS 子类继承父类属性和方法
class Father {
constructor() {}
money(c) {
let coins = 100;
c ? coins=coins/2 : coins;
console.log(coins)
}
}
new Father().money(); // 100
class Son extends Father {}
var son = new Son();
son.money(true); // 100/2
CLASS super 关键字继承中的属性或者方法
// 父类有加法方法
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类加法方法 同时 扩展减法方法
class Son extends Father {
constructor(x, y) {
// 利用super 调用父类的构造函数
// super 必须在子类this之前调用
super(x, y);
this.x = x;
this.y = y;
}
subtract() {
console.log(this.x - this.y);
}
}
var son = new Son(5, 3);
son.subtract();
son.sum();
构造函数中的静态、实例成员
// 构造函数中的属性和方法我们称为成员, 成员可以添加
function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function () {
console.log('我会唱歌');
};
}
var ldh = new Star('刘德华', 18);
// 1.实例成员就是构造函数内部通过this添加的成员 uname age sing 就是实例成员
// 实例成员只能通过实例化的对象来访问
console.log(ldh.uname);
ldh.sing();
// console.log(Star.uname); // 不可以通过构造函数来访问实例成员
// 2. 静态成员 在构造函数本身上添加的成员 sex 就是静态成员
Star.sex = '男';
// 静态成员只能通过构造函数来访问
console.log(Star.sex);
console.log(ldh.sex); // 不能通过对象来访问
在循环中使用 setinterval 并在内部清除定时器
// 关键点:勿直接在循环内定义使用定时器,需要封装为函数后再循环内调用,否则无法终止定时器
function interval(i){
var interval = setInterval(function(){
i++;
i>10 ? clearInterval(interval) : false;
console.log(i); // i>10 终止运行
}, 10);
}
for(let i=0;i<list.length;i++){
interval(i); // i>10 (正常)终止运行
// var interval = setInterval(function(){
// i++;
// i>10 ? clearInterval(interval) : false;
// console.log(i); // 达成条件后无法终止运行
// }, 10);
}
正则函数匹配中英文字符串数量
const cn_text = "世界,你好!",
en_text = "You forget a thousand things every day. How about you make sure this is one of them?",
mx_text = "世界,You forget a thousand things every day. 你好!How about you make sure this is one of them?";
var cn_count = (str, out=true)=>{
let res = str.match(/\p{sc=Han}/gu);
return out ? res.length : res;
},
en_count = (str, out=true)=>{
let res = str.replace(/[^\w-]/g, ' ').split(/\s+/).filter(w => {
return ['', '-', '_'].indexOf(w.trim()) === -1
}); //str.replace(/[^\w-]/g, ' ').trim().split(/\s+/)
return out ? res.length : res;
},
mx_count = (str, out=true)=>{
let cn = str.match(/\p{sc=Han}/gu),
en = str.replace(/[^\w-]/g, ' ').split(/\s+/).filter(w => {
return ['', '-', '_'].indexOf(w.trim()) === -1
}),
arr = [cn,en];
if(out){
if(cn && en){
return cn.length + en.length;
}else if(cn){
return cn.length;
}else if(en){
return en.length;
}else{
return arr
}
}else{
return arr
}
};
//中文
cn_count(cn_text); //4
cn_count(cn_text, false); //(4) ['世', '界', '你', '好']
//英文
en_count(en_text); //17
en_count(en_text, false); /* (17) ['You', 'forget', 'a', 'thousand', 'things', 'every', 'day', 'How', 'about', 'you', 'make', 'sure', 'this', 'is', 'one', 'of', 'them'] */
//混合
mx_count(cn_text); //4
mx_count(en_text); //17
mx_count(mx_text); //21
mx_count(mx_text, false); //(2) [Array(4), Array(17)]
递归实现“由快变慢”定时器
// https://www.cnblogs.com/wxy0/p/13496025.html
var counter = 0;
var myFunction = function(){
clearInterval(interval);
counter++;
interval = setInterval(myFunction, counter); //内部调用函数本身
console.log(counter)
}
var interval = setInterval(myFunction, counter);
js监听滚动视图实现 lazyLoad 懒加载
// lazyload js https://www.jb51.net/article/216692.htm
const bodyimg = document.querySelectorAll("img");
if(bodyimg.length>=1){
for(let i=0;i<bodyimg.length;i++){
let eachimg = bodyimg[i],
datasrc = eachimg.dataset.src;
eachimg.getBoundingClientRect().top < window.innerHeight ? eachimg.src = datasrc : false; //检查并加载当前视图页面图片
window.addEventListener('scroll', function(){
if(eachimg.getBoundingClientRect().top < window.innerHeight){ // height-sheight<=wheight 判断图片是否将要出现
eachimg.src = datasrc; // 出现后将自定义地址转为真实地址
}
})
}
}
js 图片懒加载集成函数封装(异步监听,滚动节流控制,加载延迟,错误处理,RAF支持等)
function loadlazy(imgs,offset=0,scroll=true){
const imglist = document.querySelectorAll(imgs),
loadimg = "https://img.2broear.com/images/loading_3_color_tp.png",
raf_available = window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame;
if(imglist.length<=0) return;
var timer_throttle = null,
loadArray = [...imglist],
time_delay = 500,
msgObject = Object.create(null),
autoLoad = function(imgLoadArr){
for(let i=0,arrLen=imgLoadArr.length;i<arrLen;i++){
let eachimg = imgLoadArr[i],
datasrc = eachimg.dataset.src;
eachimg.src = loadimg; //pre-holder(datasrc only)
new Promise(function(resolve,reject){
resolve(imgLoadArr);
}).then(function(res){
if(eachimg.getBoundingClientRect().top>=window.innerHeight || eachimg.offsetParent==null) return;
// var temp = new Image();
// temp.src = datasrc; //请求一次
// temp.onload = function(){
eachimg.src = datasrc; // 即时更新 eachimg(设置后即可监听图片 onload 事件)
// 使用 onload 事件替代定时器或Promise,判断已设置真实 src 的图片加载完成后再执行后续操作
eachimg.onload=function(){
if(this.getAttribute('src')===datasrc){
res.splice(res.indexOf(this), 1); // 移除已加载图片数组(已赋值真实 src 情况下)
}else{
this.removeAttribute('data-src'); // disable loadimg
this.src = datasrc; // this.src will auto-fix [http://] prefix
time_delay = 1500; //increase delay (decrease request)
console.log(time_delay);
}
};
// handle loading-err images eachimg.onerror=()=>this.src=loadimg;
eachimg.onerror=function(){
res.splice(res.indexOf(this), 1); // 移除错误图片数组
this.removeAttribute('src');
this.removeAttribute('data-src'); // disable loadimg
this.setAttribute('alt','图片请求出现问题'); // this.removeAttribute('src');
};
// }
}).catch(function(err){
console.log(err);
});
}
},
scrollLoad = function(){
return (function(){
if(timer_throttle==null){
timer_throttle = setTimeout(function(){
if(loadArray.length<=0){
console.log(Object.assign(msgObject, {status:'lazyload done', type:'call'}));
window.removeEventListener('scroll', scrollLoad, true);
return;
};
autoLoad(loadArray);
// console.log('throttling..',loadArray);
timer_throttle = null; //消除定时器
}, time_delay, loadArray); //重新传入array(单次)循环
}
})();
};
autoLoad(loadArray);
// requestAnimationFrame support
if(!scroll) return;
window.addEventListener('scroll', function(event){
let e = event || window.event,
t = e.target || e.srcElement;
if(t!==document) return;
raf_available ? window.requestAnimationFrame(scrollLoad) : scrollLoad();
}, true);
}
正则表达式中$1, $2
// 将yyyy-mm-dd格式转换为年月日格式
function chDate1date(str){
var reg =/(\d{4})\-(\d{2})\-(\d{2})/;
return str.replace(reg,"$1年$2月$3日")
};
chDate1date('2019-08-28'); // $1指2019,$2指08,$3指28
js中++num和num++在赋值时的区别
var num_ = 0;
console.log(num_++); //0 后计算,此时num已被赋值1;
var _num = 0;
console.log(++_num)l //1 先自加然后将自加后的值用做计算值
JS Promise 异步数据处理 + 链式回调
function newPromise(parm=1){
return new Promise((resolve, reject)=>{
parm ? resolve(parm) : reject(['rejected',0]); //异步操做
});
}
newPromise().then((res)=>{
console.log('origin',res); //直接返回 resove/reject 数据
// res++; //预计算res
return new Promise((resolve, reject)=>{
console.log('lastest',res); //链式回调上次 promise 数据
resolve(++res);
console.log('++',res); //链式回调更新 promise 数据
});
}).then((res)=>{
// res++; //预计算res
return new Promise((resolve, reject)=>{
console.log('lastest',res); //链式回调上次 promise 数据
resolve(++res);
console.log('++',res); //链式回调更新 promise 数据
});
}).catch((err)=>{
console.log(err);
});
js 判断对象
function isObj(obj){
return Object.prototype.toString.call(obj)==='[object Object]';
}
isObj(Object.create(null)); //true
JS 对象深拷贝
var deepCopy = (obj) => {
var ret = {}
for (var key in obj) {
var value = obj[key]
ret[key] = typeof value === 'object' ? deepCopy(value) : value
}
return ret
}
JS闭包模拟私有方法 闭包 – JavaScript | MDN (mozilla.org)
//闭包(匿名函数单次调用)
var Counter = (function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function(i=1) {
changeBy(i);
},
decrement: function(d=1) {
changeBy(-d);
},
value: function() {
return privateCounter;
}
}
})();
console.log(Counter.value()); /* logs 0 */
Counter.increment(); /* logs 1 */
Counter.increment(10); /* logs 11 */
Counter.decrement(); /* logs 10 */
Counter.decrement(10); /* logs 0 */
//闭包(声明函数多次调用)
var makeCounter = function() {
var privateCounter = 0;
function changeBy(val) {
privateCounter += val;
}
return {
increment: function(i=1) {
changeBy(i);
},
decrement: function(d=1) {
changeBy(-d);
},
value: function() {
return privateCounter;
}
}
};
var counter1 = makeCounter();
counter1.value(); /* logs 0 */
counter1.increment(); /* logs 1 */
counter1.increment(10); /* logs 11 */
counter1.decrement(); /* logs 10 */
counter1.decrement(10); /* logs 0 */
// 每次调用其中一个计数器时,通过改变这个变量的值,会改变这个闭包的词法环境。然而在一个闭包内对变量的修改,不会影响到另外一个闭包中的变量。
var counter2 = makeCounter();
counter2.value(); /* logs 0 */
counter2.increment(); /* logs 1 */
counter2.increment(10); /* logs 11 */
counter2.decrement(); /* logs 10 */
counter2.decrement(10); /* logs 0 */
JS构造对象方法到原型(取消闭包优化性能)
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
// 以下方法造成每次调用构造器时,方法都会被重新赋值一次
// this.getName = function() {
// return this.name;
// };
// this.getMessage = function() {
// return this.message;
// };
}
function MyObject(name, message) {
this.name = name.toString();
this.message = message.toString();
}
// 避免使用闭包,在原型中设置对象共享方法
MyObject.prototype.getName = function() {
return this.name;
};
MyObject.prototype.getMessage = function() {
return this.message;
};
class类的创建与继承
class Polygon {
constructor(height, width) {
this.name = 'Polygon';
this.height = height;
this.width = width;
}
}
// 重复声明一个类会引起类型错误
class Square extends Polygon {
constructor(length) {
super(length, length); //构造函数中使用的 super() 只能在构造函数中使用,并且必须在使用 this 关键字前调用
this.name = 'Square';
}
}
break 中止当前执行 functions 函数
(function() {
block_1: {
console.log('1');
break block_1;
console.log('2'); // Skiped
}
})();
// childModule1.js 中
let myFunction = ...; // assign something useful to myFunction
let myVariable = ...; // assign something useful to myVariable
export {myFunction, myVariable};
// childModule2.js 中
let myClass = ...; // assign something useful to myClass
export myClass;
// parentModule.js 中
// 仅仅聚合 childModule1 和 childModule2 中的导出
// 以重新导出他们
export { myFunction, myVariable } from 'childModule1.js';
export { myClass } from 'childModule2.js';
// 顶层模块中
// 我们可以从单个模块调用所有导出,因为 parentModule 事先
// 已经将他们“收集”/“打包”到一起
import { myFunction, myVariable, myClass } from 'parentModule.js'
js对象原型(在原型上定义方法)
const personPrototype = {
greet() {
console.log(`你好,我的名字是 ${this.name}!`);
},
};
function Person(name) {
this.name = name;
}
Object.assign(Person.prototype, personPrototype);
// new Person(123).__proto__
console.log(new Person('test').greet()); // 你好,我的名字是 test!
console.log(Object.hasOwn(irma, "name")); // 自有属性
console.log(Object.hasOwn(irma, "greet")); // false
原型与继承
例如,如果我们正在为一所学校建模,我们可能有教授和学生:他们都是人,所以有一些共同的特征(例如,他们都有名字),但每个人都可能增加额外的特征(例如,教授有一个他们所教的科目),或者可能以不同的方式实现同一个特征。在一个 OOP 系统中,我们可以说教授和学生都继承自人。
构造函数类与实例
const Person={
name: '',
teaches: '',
constructor: function(name,teaches){
Person.name = this.name = name;
Person.teaches = this.teaches = teaches;
Object.assign(Person.constructor.prototype, Person.methods);
},
methods:{
intro() {
//'this' is Person.constructor()
return 'i am '+this.name+', i teaches '+this.teaches;
}
}
}
const a = new Person.constructor('a',1);
a; //[[prototype]] method->intro
a.name; //a
a.teaches; //1
a.intro(); //'i am a, i teaches 1'
解构赋值函数提取值
function parseProtocol(url) {
const parsedURL = /^(\w+):\/\/([^/]+)\/(.*)$/.exec(url);
if (!parsedURL) {
return false;
}
console.log(parsedURL);
// ["https://developer.mozilla.org/zh-CN/docs/Web/JavaScript",
// "https", "developer.mozilla.org", "zh-CN/docs/Web/JavaScript"]
const [, protocol, fullhost, fullpath] = parsedURL;
return protocol;
}
parseProtocol("https://developer.mozilla.org/zh-CN/docs/Web/JavaScript"); //https
解构对象函数参数传递(默认只及自定义变量)
const user = {
id: 42,
displayName: "jdoe",
fullName: {
// firstName: "Jane",
lastName: "Doe",
},
};
function whois({ displayName=1, fullName:{firstName: name=2}, default_key=3 }) {
return `${displayName} is ${name} nor ${default_key}`;
}
whois(user); // "jdoe is Jane"
for 循环迭代解构
const people = [
{
name: "Mike Smith",
family: {
mother: "Jane Smith",
father: "Harry Smith",
sister: "Samantha Smith",
},
age: 35,
},
{
name: "Tom Jones",
family: {
mother: "Norah Jones",
father: "Richard Jones",
brother: "Howard Jones",
},
age: 25,
},
];
for({name: n,family: { father: f }} of people){
console.log(`Name: ${n}, Father: ${f}`);
}
// Name: Mike Smith, Father: Harry Smith
// Name: Tom Jones, Father: Richard Jones
for(let i=0;i<people.length;i++){
const {name:n,family:{father:f}} = people[i];
console.log(`Name: ${n}, Father: ${f}`);
}
组合数组对象解构(对象查找原型链)
const props = [
{
id: 1,
name: "Fizz",
__proto__: {
prot: "Fizz Prototype"
}
},
{ id: 2, name: "Buzz" },
{ id: 3, name: "FizzBuzz" },
];
const [{prot}, {id}, {name}] = props;
//prot "Fizz Prototype"
//id "2"
//name "FizzBuzz"
Javascript 面向对象OO 寄生组合继承(Object.create 可平替 object/inheritPrototype 但无法增强 constructor)
只调用了一次SuperType构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。
与此同时,原型链还能保持不变;因此,还能够正常使用instanceof和isPrototypeOf()。
function object(o){
function F(){}
F.prototype = o;
// 返回浅复制传入对象 o 构造函数 F 原型
return new F();
}
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
// SubType.prototype = Object.create(SuperType.prototype);
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
模块私有变量共有方法
var singleton = function(){
//私有变量和私有函数
var privateVariable = 10;
function privateFunction(){
return false;
}
//特权/公有方法和属性
return {
publicProperty: true,
publicMethod : function(){
privateVariable++;
return privateFunction();
}
};
}();
对象函数节流
var processor = {
timeoutId: null,
//实际进行处理的方法
performProcessing: function(){
console.log('processing..', this);
},
//初始处理调用的方法
process: function(){
clearTimeout(this.timeoutId);
var that = this;
this.timeoutId = setTimeout(function(){
that.performProcessing();
}, 1000);
}
};
//尝试开始执行
let processing = processor.process.bind(processor); // binding processor context
window.addEventListener('scroll', processing); // bind event
JS 理论
队列任务执行顺序:Tasks, microtasks, queues and schedules – JakeArchibald.com
console.log(1); // 直接执行
setTimeout(function() {
console.log(2); // 进入宏任务队列
})
new Promise(function(resolve) {
console.log(3); //直接执行
resolve()
}).then(function() {
console.log(4); // 进入微任务队列
})
console.log(5); // 直接执行
// 打印结果: 1、3、5、4、2
变量提升(隐式全局变量)与作用域链:var – JavaScript | MDN (mozilla.org)
console.log(a, b); //全局a=undefined, 全局b=undefined
var a = 1, b = 1;
function fn() {
//此处访问的变量a为下方变量提升的局部变量:var a;//undefined,变量b为函数外的全局变量b;//1)
console.log('a='+a, 'b='+b); //局部a=undefined, 全局b=1
//此处设置:局部变量a=2(提升至函数内顶级作用域链); 全局变量b=2;
var a=b=2; //等同于 var a=2;(变量提升) b=2;(全局修改)
console.log('a='+a, 'b='+b); //局部a=2, 全局b=2
}
fn();
console.log(a, b); //全局a=1, 全局b=2
CSS 速记
使用 rgba(255, 255, 255, 0) 代替 transparent 兼容 safari 环境下 -webkit-linear-gradient 渐变透明变黑
body{
/* transparent not working on safari */
background: -webkit-linear-gradient(left,red 0%,transparent 100%);
/* rgba works just fine on safari */
background: -webkit-linear-gradient(left,red 0%,rgba(255, 255, 255, 0) 100%);
}
使用 prefers-color-scheme
进行浏览器亮/暗色默认行为切换
@media (prefers-color-scheme: light) {
body{
color:white;
background:black;
}
}
@media (prefers-color-scheme: dark) {
body{
color:blank;
background:white;
}
}
在 html
添加 scroll-behavior
属性实现平滑滚动(配合js原生api scroll/scrollTo/scrollBy
使用)
html{
scroll-behavior: smooth;
}
鼠标经过文字后划过高亮背景
a:hover{
background-size: 100% 30%;
}
a{
transition: background-size .5s ease;
background: linear-gradient(red 0%, red 100%) no-repeat left 87%/0 30%;
}
笔记参考链接: HOE:JavaScript 之神妙之处、ECMAScript6 基础语法 | Gahotx’s blog、JavaScript 函数进阶 | Gahotx’s blog
评论留言
既来之则留之~ 欢迎在下方留言评论,提交评论后还可以撤销或重新编辑。(Valine 会自动保存您的评论信息到浏览器)