07. JavaScript 基础语法

lishihuan大约 13 分钟

07. JavaScript 基础语法

https://developer.mozilla.org/zh-CN/docs/Learn/Getting_started_with_the_webopen in new window

异步函数/回调

async 是一个修饰符,被它定义的函数会默认的返回一个 Promise 的 resolve的值。 因此对 async 函数可以直接进行 then 操作,返回的值即为 then() 方法的传入函数。

// demo
async function demo_1() {
    console.log('a')
    return 1
}
demo_1().then(res => { 
  console.log(res)   //  a, 1,
})  

使用html5缓存数据,通信

待整理:跨浏览器窗体消息通讯

缓存都存在跨域问题,如果想解决跨域,可以考虑 使用通讯,例如 1.window.postMessage,2.基于netty搭建websocket

https://blog.csdn.net/zerocher/article/details/72822108open in new window

https://blog.csdn.net/tang_yi_/article/details/79401280open in new window

sessionStorage localStorage 实现缓存

对浏览器来说,使用 Web Storage 存储键值对比存储 Cookie 方式更直观,而且容量更大,它包含两种:localStorage 和 sessionStorage

  1. sessionStorage(临时存储) :为每一个数据源维持一个存储区域,在浏览器打开期间存在,包括页面重新加载
  2. localStorage(长期存储) :与 sessionStorage 一样,但是浏览器关闭后,数据依然会一直存在
  • localStorage ttps://www.jianshu.com/p/8c4cee29d532 (解决跨域场景)
//将数组转成字符串存到页面缓存
var appUser=[{Ids: "1,2", Names: "李,林"},{Ids: "1,2", Names: "周,吴"}];
window.localStorage["appUser"] = JSON.stringify(appUser);
//读取页面缓存转成数组
var appUser = JSON.parse(window.localStorage["appUser"]);
console.log(appUser);
// 删除
localStorage.removeItem("key");
//删除所有
localStorage.clear();

// 保存数据语法:
localStorage.setItem("key", "value");
//读取数据语法:
var lastname = localStorage.getItem("key");



//Storage 发生变化(增加、更新、删除)时的 触发,同一个页面发生的改变不会触发,只会监听同一域名下其他页面改变 Storage
window.addEventListener('storage', function (e) {
  console.log('key', e.key); console.log('oldValue', e.oldValue);
  console.log('newValue', e.newValue); console.log('url', e.url);
})

开发记录

1.JS获取当前时间并格式化

  • 方式一
var myDate = new Date();
myDate.getYear(); //获取当前年份(2位)
myDate.getFullYear(); //获取完整的年份(4位,1970-????)
myDate.getMonth(); //获取当前月份(0-11,0代表1月)
myDate.getDate(); //获取当前日(1-31)
myDate.getDay(); //获取当前星期X(0-6,0代表星期天)
myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数)
myDate.getHours(); //获取当前小时数(0-23)
myDate.getMinutes(); //获取当前分钟数(0-59)
myDate.getSeconds(); //获取当前秒数(0-59)
myDate.getMilliseconds(); //获取当前毫秒数(0-999)
myDate.toLocaleDateString(); //获取当前日期
var mytime=myDate.toLocaleTimeString(); //获取当前时间
myDate.toLocaleString( ); //获取日期与时间
  • 方式二
// 对Date的扩展,将 Date 转化为指定格式的String
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符, 
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字) 
// 例子: 
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 
// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18 
Date.prototype.Format = function (fmt) {
    var o = {
        "M+": this.getMonth() + 1, //月份 
        "d+": this.getDate(), //日 
        "H+": this.getHours(), //小时 
        "m+": this.getMinutes(), //分 
        "s+": this.getSeconds(), //秒 
        "q+": Math.floor((this.getMonth() + 3) / 3), //季度 
        "S": this.getMilliseconds() //毫秒 
    };
    if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
    for (var k in o)
    if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
    return fmt;
}
 
调用: 
var date1 = new Date().Format("yyyy-MM-dd");
var date2 = new Date().Format("yyyy-MM-dd HH:mm:ss");

2. this 获取

function tabSwitch(this_,id){
	console.log(this_);//1.dom
	console.log(document.getElementById(id));// 2. dom
	console.log($("#"+id));//3.
}
=== 上面的2个方法输出的都是dom元素
<div id="opKsLxTab" class="middle_head_tab check" onclick="tabSwitch(this,'opKsLxTab');">
	<div class="middle_head_tab_font">
		快速巡视<span id="opKsLxTab_num" class="middle_head_tab_num">0</span>
	</div>
</div>

===== 3.输出的是 jq 对象
{
    "0": {},
    "length": 1,
    "context": {
        "location": {
            "ancestorOrigins": {
                "0": "http://localhost:8082"
            },
            "href": "http://localhost:8082/XJB/a/jkzx/jkzxModule/mainContent?deptId=20151018105049494822_ahsbd",
            "origin": "http://localhost:8082",
            "protocol": "http:",
            "host": "localhost:8082",
            "hostname": "localhost",
            "port": "8082",
            "pathname": "/XJB/a/jkzx/jkzxModule/mainContent",
            "search": "?deptId=20151018105049494822_ahsbd",
            "hash": ""
        },
        "jQuery183041088667546385205": 1,
        "docMD": true
    },
    "selector": "#opKsLxTab"
}

image-20220310092842890
image-20220310092842890

3. 第一次立即执行 setInterval 函数

_updateVieweaseToken() {
    console.log('开始执行定时器----------')
    const delay = 1000 * 60 * 60 * 24;
    (function fo() {
        console.log('业务代码================')
        setTimeout(fo, delay);
    })();
}
_updateVieweaseToken() {
    console.log('开始执行定时器----------')
    const delay = 1000 * 60 * 60 * 24;
    const this_ = this;
    (function updateVieweaseToken() {
        this_.getVieweaseInfo();
        setTimeout(updateVieweaseToken, 8000);
    })();
},
    getVieweaseInfo() {
        console.log('业务代码================');
    },

||)逻辑或运算符,第二行代码使用的是 nullish(??) 合并运算符

|| 运算符: undefined、null、0、'' 等 取 右侧 表达式的值(需要注意这个0 )

??运算符: undefined、null 取 右侧 表达式的值

console.log(null ? ? 42) //42
console.log(null || 42) //42
console.log(undefined ? ? 42) //42
console.log(undefined || 42) //42
console.log(false ? ? 42) //false
console.log(false || 42) //42
console.log('' ? ? 42) //''
console.log('' || 42) //42
console.log(0 ? ? 42) //0    ============== 注意区别
console.log(0 || 42) //42    ============== 注意区别
console.log(NaN ? ? 42) //NaN
console.log(NaN || 42) //42
callback && callback()
let str = str || ''
disabled ??= true; // 等价于 disabled = disabled === undefined ? true : disabled;

id = id ?? '1';// 默认赋初值,如果id为空则赋值 为 1
/**
*	title 可能没传递 则默认为空  title = title||'' ;
*	disabled 如果为 undefined 则默认为true ,如果为false则终止 业务代码
*/
showDatePopup (title,disabled) {
    title = title||'' ;
    disabled ??= true; // 等价于 disabled = disabled === undefined ? true : disabled;
    if(!disabled){ 
        return;// 终止业务代码执行
    }
   // 业务代码
},

JavaScript 中的空值合并运算符

if (item.placeholder){
    this.placeholder = item.placeholder
}
// 等价于
this.placeholder = item.placeholder ?? this.placeholder;
item.matr?.map(innerItem =>innerItem.name).join('、') ?? '';

数值转换

1. 数字转字符串

const num = 123;

const str1 = num.toString();
console.log(str1); // 输出 '123'

const str2 = String(num);
console.log(str2); // 输出 '123'

js 加减乘除浮点型精确运算方法

var aa=floatObj.divide(totalCost,workDays);

var floatObj = function () {
        /*
         * 判断obj是否为一个整数
         */
        function isInteger(obj) {
            return Math.floor(obj) === obj
        }
        /*
         * 将一个浮点数转成整数,返回整数和倍数。如 3.14 >> 314,倍数是 100
         * @param floatNum {number} 小数
         * @return {object}
         *   {times:100, num: 314}
         */
        function toInteger(floatNum) {
            var ret = {times: 1, num: 0};
            if (isInteger(floatNum)) {
                ret.num = floatNum;
                return ret
            }
            var strfi = floatNum + '';
            var dotPos = strfi.indexOf('.');
            var len = strfi.substr(dotPos + 1).length;
            var times = Math.pow(10, len);
            var intNum = parseInt(floatNum * times + 0.5, 10);
            ret.times = times;
            ret.num = intNum;
            return ret
        }
 
        /*
         * 核心方法,实现加减乘除运算,确保不丢失精度
         * 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
         *
         * @param a {number} 运算数1
         * @param b {number} 运算数2
         * @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
         *
         */
        function operation(a, b, op) {
            var o1 = toInteger(a);
            var o2 = toInteger(b);
            var n1 = o1.num;
            var n2 = o2.num;
            var t1 = o1.times;
            var t2 = o2.times;
            var max = t1 > t2 ? t1 : t2;
            var result = null;
            switch (op) {
                case 'add':
                    if (t1 === t2) { // 两个小数位数相同
                        result = n1 + n2
                    } else if (t1 > t2) { // o1 小数位 大于 o2
                        result = n1 + n2 * (t1 / t2)
                    } else { // o1 小数位 小于 o2
                        result = n1 * (t2 / t1) + n2
                    }
                    return result / max;
                case 'subtract':
                    if (t1 === t2) {
                        result = n1 - n2
                    } else if (t1 > t2) {
                        result = n1 - n2 * (t1 / t2)
                    } else {
                        result = n1 * (t2 / t1) - n2
                    }
                    return result / max;
                case 'multiply':
                    result = (n1 * n2) / (t1 * t2);
                    return result;
                case 'divide':
                    result = (n1 / n2) * (t2 / t1);
                    return result
            }
        }
 
        // 加减乘除的四个接口
        function add(a, b) {
            return operation(a, b, 'add')
        }
 
        function subtract(a, b) {
            return operation(a, b, 'subtract')
        }
 
        function multiply(a, b) {
            return operation(a, b, 'multiply')
        }
 
        function divide(a, b) {
            return operation(a, b, 'divide')
        }
 
        // exports
        return {
            add: add,
            subtract: subtract,
            multiply: multiply,
            divide: divide
        }
    }();

检查对象是否具有指定名称的属性 hasOwnProperty

hasOwnProperty是JavaScript中的一个对象方法,用于检查对象是否具有指定名称的属性。这个方法是继承自Object.prototype的。

使用hasOwnProperty方法,你可以确定一个对象是否直接拥有该属性,而不是通过原型链从其他对象继承获得的。

以下是hasOwnProperty方法的语法:

object.hasOwnProperty(property)
  • object:要检查的对象。
  • property:要检查的属性的名称,可以是字符串或Symbol类型。

hasOwnProperty方法会返回一个布尔值,如果对象包含具有指定名称的属性,则返回true,否则返回false

以下是一个示例:

const obj = {
  prop1: 'value1',
  prop2: 'value2'
};

console.log(obj.hasOwnProperty('prop1')); // 输出 true
console.log(obj.hasOwnProperty('toString')); // 输出 false,toString是继承自原型链的属性

在上述示例中,我们创建了一个名为obj的对象,并使用hasOwnProperty方法来检查它是否具有名为prop1toString的属性。prop1obj对象自身的属性,因此返回true,而toString是通过原型链继承的属性,所以返回false

其他方式

Object.keys(obj).indexOf(prop1) > -1 判断obj 中是否有prop1 属性

循环取数

场景: 有个颜色数组,我数据需要从中拿到颜色,考虑数据的量不可控,所以通过循环取

let colors = ['#FF5733', '#33FF57', '#3357FF'];  // 假设颜色数组有 3 个元素
let dataObject = {
    item1: '',
    item2: '',
    item3: '',
    item4: '',
    item5: ''
};

let keys = Object.keys(dataObject);

keys.forEach((key, index) => {
    let color = colors[index % colors.length];  // 通过取余实现循环
    dataObject[key] = color;
});

console.log(dataObject);

案例:

js 实现文字滚动

index.html

时钟

time.html

js 实现手机拖拽

左右滑

image-20221219091459679
image-20221219091459679

回调顶部的实现

        scrollToTop() {
            var timer = null;
            //timer的目的是实现缓慢向上滚动的效果
            timer = setInterval(function () {
                var ct = document.documentElement.scrollTop || document.body.scrollTop;
                ct -= 50;
                if (ct > 0) {
                    window.scrollTo(0, ct);
                } else {
                    window.scrollTo(0, 0);
                    clearInterval(timer);
                }
            }, 10);
        },

字符串截取

1.

2.substring

3. indexOf

4. 案例

splitName(name,str_length){
    name=name.toLowerCase();
    return name.substring(name.indexOf('k')+1,name.length);//  1000k湖AⅠ ===> 湖AⅠ
}

截取出中文

	var NewsContent = '这是内容22fsdfsdfs';
	var reg = /[\u4e00-\u9fa5]/g;
	var names = NewsContent.match(reg);
	names = names.join("");
	console.log(names);

无限循环数组

for (var i=0;i<=100;i++){
  console.log(parseInt( index % 8));// 满8个重新循环
}

回调


把url后面的参数转化成对象的形式

参考:https://blog.csdn.net/congxue666/article/details/123031293open in new window

  • 原板
function getQuery(url) {
  const index = url.indexOf('?');
  const obj = {};
  if(index === -1) return obj;
  const queryStr = url.slice(index + 1);
  const arr = queryStr.split('&');
  for(item of arr) {
    const keyValue = item.split('=');
    obj[keyValue[0]] = keyValue[1]
  }
  return obj;
}
getQuery('https://www.jianshu.com/u/98ab8b7e6c50?name=shaonian&age=18&sex=man') // {name: shaonian, age: 18, sex: man}

  • 改版
export const parseQueryString = (url,item) =>{
   if(!url){
       return ;
   }
    var params =url;
   if(url.indexOf("?")!=-1){// 说明完整的url
       params = params.split('?')[1];
   }
    var arr = (params.split('&'));
    arr.forEach((v, i) => {/*  */
        let str=v.split('=')[1];
        if(str.indexOf('%')===-1){
            item[v.split("=")[0]] =v.split("=")[1];
        }else{
            item[v.split("=")[0]] =JSON.parse(decodeURIComponent(v.split("=")[1]));
        }

    })
    return item;
};

padStart()方法,padEnd()方法

ES2017 引入了字符串open in new window补全长度的功能 如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。

如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'
'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

上面代码中,padStart()padStart()一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。

如果原字符串的长度,等于或大于指定的最小长度,则返回原字符串。

 'xxx'.padStart(2, 'ab') // 'xxx'
 'xxx'.padEnd(2, 'ab') // 'xxx'

如果用来补全的字符串与原字符串,两者的长度之和超过了指定的最小长度,则会截去超出位数的补全字符串。

 'abc'.padStart(10, '0123456789')// '0123456abc'

如果省略第二个参数,默认使用空格补全长度。

 'x'.padStart(4) // '   x'
 'x'.padEnd(4) // 'x   '

padStart()的常见用途是为数值补全指定位数。下面代码生成 10 位的数值字符串。

 '1'.padStart(10, '0') // "0000000001"
 '12'.padStart(10, '0') // "0000000012"
 '123456'.padStart(10, '0') // "0000123456"

另一个用途是提示字符串格式。

 '12'.padStart(10, 'YYYY-MM-DD') // "YYYY-MM-12"
'09-12'.padStart(10, 'YYYY-MM-DD') // "YYYY-09-12"
  • 案例:时间格式化,补全2位数值
// 返回 2021-06-02
let year = dt.getFullYear()
let month = (dt.getMonth() + 1).toString().padStart(2, '0')
let date = dt.getDate().toString().padStart(2, '0')
return `${year}-${month}-${date}`

js 时间

1. new Date() 相关

	let time = new Date();  //获取当前时间  Tue May 11 2021 18:42:51 GMT+0800 (中国标准时间)
    let year = time.getFullYear();  //获取年 2021
    let month = time.getMonth() + 1;  //获取月  5
    let day = time.getDate();    //获取天  11
    let h = time.getHours();   //获取小时  18
    let m = time.getMinutes();  //获取分钟  42
    let s = time.getSeconds();    //获取秒  51
    let weekDay = time.getDay();  //获取星期  2

2. 计算当前时间对应本月对应的周

  • 相对于本月
const dayjs = require('dayjs');

// 获取当前日期
const date = dayjs();

// 获取当月的第一天
const firstDayOfMonth = date.startOf('month');

// 计算当前日期是当月的第几周
const weekNumber = date.week() - firstDayOfMonth.week() + 1;

console.log(weekNumber);
  • 相对本年
const dayjs = require('dayjs');

// 获取给定日期的周数
const date = dayjs('2023-07-21');
const weekNumber = date.isoWeek();

console.log(weekNumber);

在上述示例中,我们创建了一个 dayjs 对象 date,表示给定的日期(例如:'2023-07-21')。然后,我们使用 isoWeek() 方法获取该日期所在的周数,并将结果赋值给 weekNumber。最后,通过打印输出,你将得到给定日期所在的周数。

注意,这里使用的是 ISO 周计算方式,即周一为一周的起始,周日为一周的结束。如果你希望使用其他的计算方式,如以周日为一周的起始,可以使用 week() 方法来代替 isoWeek() 方法。

const weekNumber = date.week();

这样,你就可以计算给定日期是一年中的第几周了。

js时间案例

1. 字符串日期对比当前日期

/**
 * 日期比对
 * 返回值 >0 表示指定日期在今天之后,<0 表示之前 , =0 则表示 相等
 * @param timeString
 */
export const dateComparison=(dateStr)=>{
  // 将时间字符串转换为日期对象
  const timeDate = new Date(dateStr);
  timeDate.setHours(0, 0, 0, 0); // 将时间部分设为零

  // 获取当前日期的日期对象,且时间部分也设为零
  const currentDate = new Date();
  currentDate.setHours(0, 0, 0, 0);
  return timeDate.getTime() - currentDate.getTime();// >0 表示之后,<0 表示之前 , =0 则表示 相等
}

位置信息

event.clientX、event.clientY

鼠标相对于浏览器窗口可视区域的X,Y坐标(窗口坐标),可视区域不包括工具栏和滚动条。IE事件和标准事件都定义了这2个属性

event.pageX、event.pageY

类似于event.clientX、event.clientY,但它们使用的是文档坐标而非窗口坐标。这2个属性不是标准属性,但得到了广泛支持。IE事件中没有这2个属性。

event.offsetX、event.offsetY

鼠标相对于事件源元素(srcElement)的X,Y坐标,只有IE事件有这2个属性,标准事件没有对应的属性。

event.screenX、event.screenY

鼠标相对于用户显示器屏幕左上角的X,Y坐标。标准事件和IE事件都定义了这2个属性

image-20221230085453233
image-20221230085453233

如何用js获取当前URL、参数、端口、IP等服务器信息

1,设置或获取对象指定的文件名或路径。

console.log(window.location.pathname)

2,设置或获取整个 URL 为字符串。

console.log(window.location.href);

3,设置或获取与 URL 关联的端口号码。

console.log(window.location.port)

4,设置或获取 URL 的协议部分。

console.log(window.location.protocol)

5,设置或获取 href 属性中在井号“#”后面的分段。

console.log(window.location.hash)

6,设置或获取 location 或 URL 的 hostname 和 port 号码。

console.log(window.location.host)

7,设置或获取 href 属性中跟在问号后面的部分。

console.log(window.location.search)

8,获取变量的值(截取等号后面的部分)

var url = window.location.search;

9,用来得到当前网页的域名

//url:   http://192.168.6.203:18187/SDT_IMOA/a?login
function getRootPath() {
    //获取当前网址,
    var curPath = window.document.location.href; // http://192.168.6.203:18187/SDT_IMOA/a?login
    //获取主机地址之后的目录,
    var pathName = window.document.location.pathname; //  /SDT_IMOA/a
    var pos = curPath.indexOf(pathName);
    //获取主机地址
    var localhostPaht = curPath.substring(0, pos); //  http://192.168.6.203:18187
    //获取带"/"的项目名,
    var projectName = pathName.substring(0, pathName.substr(1).indexOf('/') + 1); //  /SDT_IMOA
    return (localhostPaht);
}

其他

new Image

const image = new Image()
image.setAttribute('crossOrigin', 'anonymous')
image.src = src
image.onload = () => { // es6 写法 ,否则会有this指向问题
	consolee.log(image.width)
}
//image.onload = function() { // es6 写法 ,否则会有this指向问题
//	consolee.log(image.width)
//}

中文转拼音

中文转拼音

JavaScript堆内存不足

JavaScript heap out of memory

环境变量:
NODE_OPTIONS
--max-old-space-size=4096

console.infoopen in new window 打印设置文本字体样式

  • %c 这是一种格式化占位符,用于指定后续文本的样式 对应下面的 "color:#409EFF;font-size: 22px;font-weight:bolder", 样式 也即是第一段文字需要输出的信息 设置了字体,颜色,加粗
  • ${VARIANT_FORM_VERSION} 变量的使用
var VARIANT_FORM_VERSION = 2.2.9 ;// 定义变量
console.info(`%c1. 需要输出的信息 %c2. 变量${VARIANT_FORM_VERSION}`,
             "color:#409EFF;font-size: 22px;font-weight:bolder",
             "color:#999;font-size: 12px"
            )
image-20231007144250988
image-20231007144250988