javacript笔记

本文详细探讨了JavaScript的关键概念,包括代码解析、变量提升、严格模式和冻结变量。深入讲解了NULL与Undefined的区别,以及短路运算的实用技巧。特别关注了数组与对象的区分,字符串的拼接新语法,以及Date类型的使用,如获取时间戳和日期格式化。还介绍了各种数据结构如Set、Map和Symbol,以及函数的多种用法,包括默认参数。推荐使用VSCode进行编写,并提到了相关插件和第三方库momentjs。
摘要由CSDN通过智能技术生成

JAVASCRIPT

推荐vscode进行编写,推荐相关插件安装如下:

  • live server

代码解析与变量提升

console.log(web)
var web = 'test'  
//浏览器输出undefined,原因:在代码解析的时候会把var web(变量定义)提前
var web;
console.og(web);
web = 'test';

//例子2
funtion test(){
    if(false){
        var web = 'test'
    }
    console.log(web)  //输出undefined
}
//上述例子经过代码解析后等于
funtion test(){
    var web;
    if(false){
        web = 'test'
    }
    console.log(web)  //输出undefined
}

严格模式

//test.js
funciton test(){
    a = 123
}
//test.html
<script src="test.js">
	var a = 111;
    test();
    console.log(a) //输出结果为123 ,全局参数污染
</script>

//test1.html
<script src="test.js">
    "use strict" //严格模式,变量必须声明,否则报错,当前作用域以及子作用域受影响
	var a = 111;
    test();
    console.log(a) 
</script>

冻结变量

const host = {
  url:'https://www.baidu.com',
  port:443
}
host.port = 80
console.log(host)//输出 {url: "https://www.baidu.com", port: 80}

//冻结变量host
const host = {
  url:'https://www.baidu.com',
  port:443
}
Object.freeze(host)  //冻结变量
host.port = 80
console.log(host) //输出{url: "https://www.baidu.com", port: 443}

NULL与Undefined

let config = null  //初始化引用类型 等于 let config = {}  转成数值为0
let url = undefined //初始化基础类型 等于 let url = '' 当变量被定义了未赋值时,为undefined 转成数值为NAN

短路运算的妙用

let a = 6
let b = 0
let f = b || a 
console.log(f) //输出6,原因:会把为真的值赋值给f

//例子1
let sex = prompt('请输入性别:')
let result = sex || '女'
console.log(result) 

switch注意事项

let error = "notice";
switch (error){
  case "notice":
    console.log('提示消息')     //没有写break,将会继续往下执行,直到碰到break后停止
  case "warning":
    console.log("提示或警告消息")
    break
  case "error":
  default:
    console.log('错误消息')
}
/*
最终控制台输出
test.js:4 提示消息
test.js:6 提示或警告消息
*/

区分数组与对象

/*
  使用typeof判断类型输出都是object
  应该使用 instanceof
*/
let a = [];
let b = {};
console.log(a instanceof Array)

字符串

拼接新语法

let name = 'chestnut'
let age = 20
console.log('我的名字叫:'+name+',我今年:'+age+'岁。')
console.log(`我的名字叫:${name},我今年:${age}岁。`) //使用${}进行变量读取

函数

//去掉字符串
str= 'a    b'
console.log(str.trim().length);

//获取指定字符
str= 'abcdsdfeow';
console.log(str[0]);
console.log(str.charAt(0))

let str = '123;sdifds;34r?';

/*
字符串截取 :
slice()
substring()
substr()
*/

/*
字符串查找 :
str.indexOf():返回具体位置,若为-1则找不到,从左边开始查找
str.lastindexOf():返回具体位置 ,从右边开始查找
str.includes():返回布尔类型
str.startsWith():是否以某字符开头,区分大小写,返回布尔类型
str.endsWith():是否以某字符结尾
*/

/*
字符串替换:
str.relace()
*/

/*
字符串重复:
str.repeat()
*/

布尔类型

隐式转换原理

let array = [1,2,4]
let num = 2
console.log(array == true) //输出为false ,因为会把array转成数值为NAN,执行Number(array),布尔true转成数值为1
console.log(num == true)//输出为false ,2不等于1
if(num) //num为true,此运行结果是将num转成布尔类型,即Boolean(num) = true

布尔类型转换

let number = 0;
console.log(typeof(number)) //输出为number
number = !!number; //转换成布尔类型
number = Boolean(number)//转换成布尔类型

NAN类型

console.log(Number('dsafd')) //输出NaN(not a number)
console.log(Number('dfo') == NaN) //输出false,原因 NaN无法与NaN进行判断
 
//可使用以下方法进行判断
console.log(Number.isNaN(1/'adfads'))
console.log(Object.is(1/'asfd',NaN))

标签模板

let name = 'chestnut'
let age = 20
let str = tag`我的名字叫:${name},我今年:${age}岁。`;
console.log(str);
function tag(strings,...vars){ //不知道有多少参数,使用...收集所有的参数形成数组
  console.log(strings); //输出数组 ["我的名字叫:", ",我今年:", "岁。"]
  console.log(vars) //输出数组['chestnut',20]
  console.log(name); //输出chestnut
  console.log(age); //输出20
  return strings.map((str,key) =>{
      return str +=vars[key]?vars[key]:'yeah!!!';  //使用tag标签可对字符串做二次处理
  })
}

Date类型

获取时间戳

const date = new Date('2021-10-12 11:30:34')
console.log(date *1)
console.log(Number(date))
console.log(date.valueOf())
console.log(date.getTime())

计算脚本执行时间

//第一种
const date = Date.now()
for(let i =0;i<=2000000;i++){
}
const end = Date.now()
console.log((end-date)/1000+'s')
//输出:5 0.003s

//第二种方式
console.time('sign') //自定义标志
for(let i =0;i<=2000000;i++){
}
console.timeEnd('sign')
//输出: sign: 2.48583984375 ms

日期格式封装


const date =Date.now()
console.log(getDate(new Date(date),'YYYY-MM-DD HH:mm:ss'))

function getDate(date,format){
  const config = {
    YYYY : date.getFullYear(),
    MM: date.getMonth()+1,
    DD: date.getDate(),
    HH: date.getHours(),
    mm: date.getMinutes(),
    ss: date.getSeconds()
  }
  for(const key in config){
    format = format.replace(key,config[key])
  }
  return format;
}
  • 第三方库推荐momentjs(日期处理库)

数组

  • 可使用console.log()与console.table()进行查看
//数组转字符串
let a = 'adf23';
console.log(Array.from(a));

let obj = {
    0:'test1',
    1:'test2'
}
console.log(Array.from(obj))//失败,使用from方法必须包含length属性

let obj1 = {
  0:'test1',
  1:'test2',
  length:2
}
console.log(Array.from(obj1))//转换成功

展开语法

let a = [123,234,34]
let b = [23,45]
let c = [...a,...b] //将a的值和b的值展开
console.log(c) //最终得到[123, 234, 34, 23, 45]

//不定参数传参
function sum(...num){
  let result = 0;
  for(let i of num){
    result += i
  }
  return result;
}

console.log(sum(1,49,23,47))
    
let list = document.querySelectorAll('div')
console.log(list) //节点对象
let _list = [...list] //转成数组
_list.map(item => {
  console.log(item)
})

解构语法

  • …放在变量位置时,吸收,放在值的位置时,是展开
//结构常见用法
let [age,name] = [20,'ella']
console.log(age)
console.log(name)

let [...arr] = 'sdfae'
console.log(arr)

let [_age,...arrs] = [20,'ella','play games']
console.log(arrs)

查找元素

  • indexof:返回查找元素下标,若找不到返回-1
  • includes:返回布尔值
  • 新增find,findIndex用法见下列案例
let arr = [{name:'aaa',age:18},{name:'bbb',age:20},{name:'ccc',age:30}]
let result = arr.find(function(item){
  return item.name == 'aaa'
})
console.log(result)//返回{name:'aaa',age:18}

let result_index = arr.findIndex(function(item){
  return item.name == 'aaa'
})
console.log(result_index)//返回0 ,对应下标

排序(sort)

let arr = [{name:'aaa',age:18},{name:'bbb',age:20},{name:'ccc',age:30}]
arr = arr.sort(function(a,b){
  return a.age - b.age  //a - b < 0 ,从小到大排列
})
console.table(arr)

arr = arr.sort(function(a,b){
  return  b.age - a.age  //b - a < 0 ,从大到小排列
})
console.table(arr)

//原理

循环

  • for in:获取索引
  • for of:获取数组的值
  • forEach:可遍历dom对象
  • every:当返回false,直接中断循环
  • some:当返回true,直接中断循环
let list = [{'title':'abc','value':1},{'title':'adasf','value':2}]
//for in...
for(let item in list){
  console.log(item) //输出下标0,1
}
//for of 
for(let time of list){
  console.log(item) //输出下标对应值  {title: "abc", value: 1} ,{title: "adasf", value: 2}
}
//forEach可遍历dom节点
let list = document.querySelectorAll('div')
list.forEach(function(item){
  item.addEventListener('click',function(){
    console.log(this.classList);
    this.classList.toggle('disable') //classList:类名列表;toggle:如果有则去除,没有则添加类名
  })
})

//every循环
let arr = [{name:'bbb',age:20},{name:'aaa',age:17},{name:'ccc',age:30}]
const flag = arr.every(function(item,index,arr){ //item:值,index:下标,arr:原数组
  console.log(item);
  return item.age > 18; //可更改条件查看控制台打印,返回false中断循环
});
if(flag){
  console.log('所有朋友都成年')
}
else{
  console.log('有人未成年')
}
//some循环
let arr = [{name:'bbb',age:20},{name:'aaa',age:17},{name:'ccc',age:30}]
const flag = arr.some(function(item,index,arr){//item:值,index:下标,arr:原数组
  console.log(item);
  return item.name === 'aaa'; //可更改条件查看控制台打印,返回true中断循环
});
if(flag){
  console.log('里面有名为aaa的人')
}
else{
  console.log('查无此人')
}

迭代器(Iterator)

  • 只要是迭代器类型,都可以使用next()
let arr = [{name:'aaa',age:18},{name:'bbb',age:20},{name:'ccc',age:30}]
let keys = arr.keys();
console.log(arr.keys()) //输出Array Iterator {},为可迭代对象
console.log(keys.next())//value:值(索引0,1,2....),done:是否迭代完成

let arr = [{name:'aaa',age:18},{name:'bbb',age:20},{name:'ccc',age:30}]
let values = arr.values();
console.log(values) //输出Array Iterator {},为可迭代对象
console.log(values.next())//value:值(索引对应的值),done:是否完成迭代
//方法一:先执行value与done分别赋值,再判断是否可以继续迭代
while(({value,done} = values.next()) && done === false){
  console.log(value); 
  //输出所有下标对应的值
  //{name: "aaa", age: 18}
  //{name: "bbb", age: 20}
  //{name: "ccc", age: 30}
} 
//方法二:
for(const value of values){
  console.log(value)
}

let entries = arr.entries()
console.log(entries);
console.log(entries.next());//value:数组[索引,值]例如:[0,{name: "aaa", age: 18}],  done:是否完成迭代

过滤

let arr = [{name:'bbb',age:20},{name:'aaa',age:17},{name:'ccc',age:30}]
const result = arr.filter(function(item,index,arr){
  return item.age>18; //返回满足条件的数组
});
console.table(result);

映射

let arr = [{name:'bbb',age:20},{name:'aaa',age:17},{name:'ccc',age:30}]
const result = arr.map(function(item,index,arr){
  item.name = `test-${item.name}`;
  return item; //每次循环返回值为最终数组对应索引的值,可尝试return 1输出结果
});
console.table(result);

reduce方法

  • 适合做数据统计
let arr = [23,21,3,1,543,23]
const _result = arr.reduce(function(pre,item,index,arr){
  //pre为上一次返回的结果
  //如果没有设置则默认第一次输出pre为0索引对应值,item为1索引对应值
  console.log(index+'次:'+pre);
  console.log(index+'次:'+item);
  return 666; 
});
console.log(_result);
const result = arr.reduce(function(pre,item,index,arr){
  return pre += item === 23?1:0
},0);
//0为初始返回结果(pre初始值)
console.log('23总共出现:'+result+'次');

//案例1:获取最大值
let arr = [23,21,3,1,543,23]
const result = arr.reduce(function(pre,item,index,arr){
  return pre > item ? pre : item;
});
console.log(`最大值为:${result}`);

//案例2:获取已成年名字
let arr = [{name:'bbb',age:20},{name:'aaa',age:17},{name:'ccc',age:30}]
const result = arr.reduce(function(pre,item,index,arr){
  if(item.age>18) pre.push(item.name);
  return pre;
},[]);
console.table(result);

symbol

  • 用来区分唯一表示的字符串
let _a = 'aaa';
let _b = 'aaa';
console.log(_a === _b);//输出true,相等

let a = Symbol('aaa')
let b = Symbol('aaa')
console.log(a.description)
console.log(b.description)
console.log(a === b) //输出false,不相等

//使用symbol.for全局声明,会在内存中记录,若存在则不创建,因此相同描述时,使用同一个
let a = Symbol.for('aaa')
let b = Symbol.for('aaa')
console.log(Symbol.keyFor(a))//使用symbol.for声明时才可以使用keyFor获取描述
console.log(a === b) 

//symbol使用案例
let a = {
  name: 'ella',
  key: Symbol()
}

let b = {
  name: 'ella',
  key: Symbol()
}

let grade = {
  [a.key]: {age: 20}, //json中key使用变量需要使用中括号
  [b.key]: {age: 30}
}

console.log(grade[a.key])

//案例2:使用symbol当key时,如何遍历
let symbol = Symbol('个人资料');
let a = {
  name: 'ella',
  [symbol]: 'ella个人资料'
}

for (const key in a) {
  console.log(key) //无法打印出symbol
}

for (const key of Object.keys(a)) {
  console.log(key); //无法打印出symbol
}

for (const key of Object.getOwnPropertySymbols(a)) {
  console.log(key); //只能打印出symbol
}

for (const key of Reflect.ownKeys(a)) {
  console.log(key); //打印所有属性
}

set与WeakSet

set

  • 不能有重复类型
//声明方式1:
let set = new Set([12,12,3,45]);
console.log(set);
//声明方式2:
let _set = new Set();
_set.add(13)
console.log(_set);

//判断是否存在
console.log(set.has(12))

//删除
set.delete(12)
console.log(set)

//清空
set.clear()

//类型转换:转换成数组
let set = new Set([12,12,3,45]);

console.log(Array.from(set)) //方法1
console.log([...set]) //方法2

set处理并集交集差集

//并集:利用不重复特性
let set = new Set([12,24,3,45,37]);
let _set = new Set([12,24,3,48,59]);
console.log(new Set([...set,..._set]))

//差集
console.log(
  new Set(
    [...set].filter(function(item){
      return !_set.has(item) //_set数组中不包含set数组的集合
    })
  )
)
//交集
console.log(
  new Set(
    [...set].filter(function(item){
      return _set.has(item) //_set数组中包含set数组的集合
    })
  )
)

WeakSet()

  • 不含有重复值
  • 里面的值必须为引用类型
  • 具有弱引用特性 – 迭代器.key ,values/for of都用不了
//let set = new WeakSet([12,24,3,45,37]); 会报错
// 报错原因:该语句是将12,24等值类型分别添加进去
let set = new WeakSet();
set.add([12,24,3,45,37]) //将引用对象[12,24,3,45,37]添加
console.log(set)

//弱引用特性案例
let _person = {name:'ella','age':20};
let a = _person;
_person = null;
console.log(a) //输出正常结果,虽然_person被清空了,但是a还是指向内存地址

let set = new WeakSet();
let person = {name:'ella','age':20};
set.add(person);
person = null;
console.log(set)//输出为空,person被删除,WeakSet增加不会引用内存地址,会被垃圾回收机制清空



案例

<body> 
  <style>
    .disable{
      color : #ccc;
    }
    .a{
      width: 100px;
      height: 20px;
      background-color: #587fff;
      margin-bottom: 3px;
    }
    .remove{
      background-color: #ccc;
    }
  </style>
    <div class="a">1</div>
    <div class="a">2</div>
    <div class="a">3</div>
    <div class="a">4</div>
    <div class="a">5</div>
    <script src="./test.js"></script>  
</body>
//test.js
class removeDiv{
  constructor(){
    this.divs = document.querySelectorAll('.a');
    this.lists = new WeakSet();
    //将dom节点添加到webkset
    this.divs.forEach(item => this.lists.add(item));
  }
  click(){
    this.divs.forEach(item => {
      item.addEventListener('click',() =>{
        //如果weakset里面有dom对象,则添加移除样式,并将dom从weakset中移除
        if(this.lists.has(item)){
          item.classList.add('remove');
          this.lists.delete(item);
        }
        else{
          //否则移除样式,并添加dom节点对象至weakset
          item.classList.remove('remove');
          this.lists.add(item);
        }
      })     
    });
  }
}
let a =new removeDiv();
a.click();

Map与WeakMap

Map

  • 键可以为任务类型,例如:对象,数值等
  • 因为可以为任意对象,所以键可以用来存储dom节点,值可以为dom的额外消息
let map = new Map();
map.set('name','ella');
console.log(map);
map.set({'a':'123'},'ella')
console.log(map);
map.set(1,'ella')
console.log(map);
map.set([1,2,3],'ella')
console.log(map);

let map = new Map();
map.set('name','ella');
let test = {'a':'123'};
map.set(test,'ella')
//查询
console.log(map.has(test));
//取值
console.log(map.get(test));//存的内存地址,可获取
console.log(map.get({'a':'123'}));//不可获取
//删除
map.delete('name');
console.log(map);
//清空
map.clear();
console.log(map)

WeakMap

  • 键只能是引用类型
  • 具有弱引用类型特性,类似于WeakSet

函数

函数声明

//声明方式1:
let fun = new Function('test','console.log(test)');//(参数,函数体)
fun('123');

//声明方式2:
funtion fun(test){
  console.log(test);
}

//声明方式3:
let _fun = funtion fun(test){
  console.log(test);
};//注意加分号

//声明方式4:
let person = {
  name : '',
  age : '',
  setPerson(name, age) {
    this.name = name;
    this.age = age;
  },
  getPerson(){
    console.log(`我的名字${this.name}是,我今年${this.age}`);
  }
}
person.setPerson('ella',20);
person.getPerson();

全局函数

function a (){
  console.log('a');
}
a()//输出a
window.a()//输出a,直接定义函数是全局函数,会增加到window对象中

var a = function b (){
  console.log('a');
}
window.a()//输出a,var声明会增加到window对象中

//解决方式,使用let进行声明
let a = function b (){
  console.log('a');
}
window.a()//报错

函数提升

b(); //输出b,声明b函数进行了提升
function b(){
  console.log('b');
}

a();//报错,匿名函数不会进行函数提升
let a = function(){
  console.log('a');
}

//箭头函数,求和案例
function sum(...args){
  return args.reduce((a,b) => a+b)
}
console.log(sum(1,2,3,10));

立即执行函数

//普通函数声明
function a(){
  console.log('aaa');
}
a();//调用函数执行
//立即执行函数,不需要调用,直接执行
(function a(){
    console.log('aaa');
})()

//解决多个js文件同名函数冲突问题
//test1.js
(function(window){
  function a(){
    console.log('1aaa');
  }
  function b(){
    console.log('1aaa');
  }
  window.test1 = {a,b};
})(window);
//test2.js
(function(window){
  function a(){
    console.log('2aaa');
  }
  function b(){
    console.log('2aaa');
  }
  window.test2 = {a,b};
})(window);

test1.a();
test2.a();

函数默认值

function sum(a=1,b=2){
   console.log(a+b);
}
sum();//未传参数使用默认值
sum(4,5);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值