首页 > 编程语言 >JavaScript随笔

JavaScript随笔

时间:2023-03-16 12:44:48浏览次数:41  
标签:obj log JavaScript start let typeof console 随笔

数据类型

简单数据类型(原始类型):Undefined、Null、Boolean、Number、String和Symbol

复杂数据类型:Object

深拷贝与浅拷贝

浅拷贝

  • Object.assign
  • Array.prototype.slice(), Array.prototype.concat()
  • 使用拓展运算符实现的复制

浅拷贝是创建一个新对象。然后将原始对象的非引用类型数据成员复制到新对象中。但是对于引用类型数据成员,新对象只是复制了原始对象中的引用,而不是创建一个新的对象。这意味着,如果原始对象和新对象中的引用类型数据成员指向同一个对象,那么对于这个对象的修改将会影响到原始对象和新对象。

我们说拷贝的深浅是区别引用类型的。

实现一个浅拷贝:

function shallowClone(obj){
    const newObj={};
    for(let prop in obj){
        if(obj.hasOwnProperty(prop)){//是自有属性
            newObj[prop]=obj[prop];
        }
    }
    return newObj;
}

深拷贝

深拷贝是创建一个新对象,然后将原始对象的所有数据成员,包括引用类型数据成员中的数据,全部复制到新对象中。这意味着,即使原始对象和新对象中的引用类型数据成员指向同一个对象,对于这个对象的修改也不会影响到原始对象和新对象。

  • _.cloneDeep()
  • jQuery.extend()
  • JSON.stringify()
  • 手写循环递归
//hash默认值类型WeakMap,防止出现循环引用导致死循环
function deepClone(obj, hash = new WeakMap()) {
  //如果是null或者undefined就不进行拷贝操作
  if (obj === null||obj===undefined) return obj;
  //如果是日期和正则表达式,返回新构造的Date和RegExp实例
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  //基本类型和函数的话不需要深拷贝
  if (typeof obj !== "object") return obj;
  //已拷贝过,直接返回拷贝值
  if(hash.get(obj)) return hash.get(obj);
  //找到的是所属类原型上的constructor,
  //而原型上的 constructor指向的是当前类本身
  let cloneObj = new obj.constructor();
  hash.set(obj, cloneObj);
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      //实现一个递归拷贝
      cloneObj[key] = deepClone(obj[key], hash);
    }
  }
  return cloneObj;
}

循环引用导致的死循环

循环引用是指两个对象相互引用,导致内存泄漏和死循环问题。

考虑以下代码:

const obj1={prop:null};
const obj2={prop:obj1};
obj1.prop=obj2;

使用简单递归算法实现深拷贝obj1就会出现死循环:

function deepClone(obj){
    if(obj === null||typeof obj!=='object') return obj;
    const cloneObj = new obj.constructor();
    for(let key in obj){
        if(obj.hasOwnProperty(obj)){
            cloneObj[key] = deepClone(obj[key]);
        }
    }
    return cloneObj;
}

const obj3 = deepClone(obj1); //死循环,卡在obj1.prop=obj2上

防抖和节流

防抖规定n秒后才执行的事件提前触发,则重新计时

实现防抖:

节流事件n秒内只执行一次,若n秒内重复触发,只有一次生效

实现节流:

ES6新特性

  1. const和let,出现块级作用域;
  2. 模板字符串,使用反引号(``)和变量或表达式界定符(${});
  3. 箭头函数(()=>{});
  4. 参数默认值(function fn(param = 'defaultValue'){});
  5. 扩展操作符(...);
  6. 二进制(0b0B前缀)和八进制(0o0O前缀)字面量;
  7. 对象和数组结构;
  8. 对象超类(super);
  9. for offor in
  10. 类(class);
  11. Promise;
  12. Symbol;
  13. Set和Map;
  14. 模块化 export和import
  15. 迭代器(Iterator);
  16. 生成器(Generator);

数组方法

数组方法分为操作、转换、排序和迭代。

操作方法

分为增、删、查、改来记忆。

一、增

  • splice(<startPos>,0,arg1,arg2,...),返回空数组;
  • push(),添加到数组末尾,返回数组新长度;
  • unshift(),添加到数组开头,返回数组新长度;
  • concat(),不影响原始数组,返回新数组

二、删

  • splice(<startPos>,<delNums>),返回被删除的项组成的数组;
  • slice(<startPos>,<endPos>),返回[startPos,endPos)下标区间的元素组成的数组,不影响元素组
  • pop(),删除数组最后一项,返回删除元素;
  • shift(),删除数组开头,返回删除元素。

三、查

  • indexOf(),返回查找项的坐标,没有就返回1;
  • includes(),查询是否包含查找项,有就返回true,否则返回false;
  • find(),返回第一个匹配的元素。

四、改

例如:splice(1,1,'modifiedValue')原数组受影响

转换方法

  • join,接受一个参数,即字符分隔符
const arr = [1,2,3]
console.log(arr.join('-'))//1-2-3

排序方法

  • sort和reverse。
const arr = [3,2,4]
function cmp(v1,v2){
  if(v1<v2) return -1;
  else if(v1>v2) return 1;
  else return 0;
}
arr.sort(cmp);//直接影响arr
console.log(arr);

迭代方法

  • some()
  • every()
  • forEach()
  • filter()
  • map()

字符串方法

concat()

slice()

substr()

subString()

trim()、trimLeft()、trimRight()

padStart()、padEnd()

toLowerCase()、toUpperCase()

正则表达式RegExp

语法:/pattern/flags

pattern(模式)包括字符类、限定符、分组、向前查找和反向引用。

flags用于控制正则表达式的行为,有如下标记:

  • g:全局模式,查找全部内容,而不是只查找第一个匹配的;
  • i:不区分大小写,查找匹配时忽略pattern和字符串的大小写;
  • m:多行模式,查找到一行末尾继续查找;
  • y:粘附模式,只查找从lastIndex开始及之后的字符串;
  • u:Unicode模式,启用Unicode匹配;
  • s:dotAll模式,表示元字符.匹配任何字符(包括换行符\n\r)。

特殊字符:

  • *的意思是前一项出现零次或者多次;
  • +意思是前一项至少出现1次;
  • ^限定开头,如果出现在字符集合模式时,表示不取;
  • $限定结尾;
  • ?前一项出现0或1次;
  • .默认匹配除换行符之外的任何字符;
  • x|y匹配x或y;
  • (),可单独匹配;
  • {n}表示前面一项出现n次;
  • {n,}表示前面一项至少出现n次;
  • {n,m}表示前面一项出现n到m次;
  • [],字符集合,用破折号(-)来指定一个字符范围,字符集中*.没有特殊含义;
  • [^],反字符集合,意思是不包括该字符集;
  • \d匹配一个数字,等价于[0-9]
  • D匹配一个非数字字符,等价于[^0-9]
  • \s匹配一个空白字符;
  • \S匹配一个非空白字符;
  • \w匹配一个单字字符(字母、数字或下划线);
  • \W匹配一个非单词字符。

使用正则表达式

  • exec,一个在字符串中执行查找匹配的 RegExp 方法,它返回一个数组(未匹配到则返回 null),RegExp方法;
  • test,返回true或false,RegExp方法;
  • match,string方法

DATE类型的API

话都在代码里了

let start = new Date();
let end = new Date(2024,1,1,11,20);
console.log('start: '+start);
console.log('start.toString(): '+start.toString());
console.log('start.toLocaleString(): '+start.toLocaleString());
console.log('start.valueOf(): '+start.valueOf());
console.log("start.toDateString(): " + start.toDateString());
console.log("start.toTimeString(): " + start.toTimeString());
console.log("start.toLocaleDateString(): " + start.toLocaleDateString());
console.log("start.toLocaleTimeString(): " + start.toLocaleTimeString());
console.log(`end-start: ${end-start}`);
console.log("start.getTime(): " + start.getTime());
console.log("几年 start.getFullYear(): " + start.getFullYear());
console.log(`几月 start.getMonth(): ${parseInt(start.getMonth())+1}`);
console.log("几日 start.getDate(): " + start.getDate());
console.log("星期几 start.getDay(): " + start.getDay());//周日为0,周一为1
console.log("几点 start.getHours(): " + start.getHours());
console.log("几分 start.getMinutes(): " + start.getMinutes());
console.log("几秒 start.getSeconds(): " + start.getSeconds());
console.log("几毫秒 start.getMilliseconds(): " + start.getMilliseconds());

输出:

start: Fri Mar 10 2023 13:16:14 GMT+0800 (中国标准时间)
start.toString(): Fri Mar 10 2023 13:16:14 GMT+0800 (中国标准时间)
start.toLocaleString(): 2023/3/10 13:16:14
start.valueOf(): 1678425374941
start.toDateString(): Fri Mar 10 2023
start.toTimeString(): 13:16:14 GMT+0800 (中国标准时间)
start.toLocaleDateString(): 2023/3/10
start.toLocaleTimeString(): 13:16:14
end-start: 28332225059
start.getTime(): 1678425374941
几年 start.getFullYear(): 2023
几月 start.getMonth(): 3
几日 start.getDate(): 10
星期几 start.getDay(): 5
几点 start.getHours(): 13
几分 start.getMinutes(): 16
几秒 start.getSeconds(): 14
几毫秒 start.getMilliseconds(): 941

=====

一、相等操作符==

  • 两个都为简单类型,字符串和布尔值都会转换成数值,再比较
  • 简单类型与引用类型比较,对象转化成其原始类型的值,再比较
  • 两个都为引用类型,则比较它们是否指向同一个对象
  • null 和 undefined 相等
  • 存在 NaN 则返回 false

二、全等操作符===

不进行类型转换

DOM操作

DOM(文档对象模型,Document Object Model),是HTML和XML文档的编程接口。

每个HTML文档都可以表示为一个层级的树形结构。

document节点表示每个文档的根节点,根节点的唯一子节点是<html>,称之为文档元素

节点属性和方法

基本属性:nodeName、nodeValue、nodeType。

父子节点关系图:

image.png

childNodes属性是包含一个NodeList的实例,NodeList是实时的活动对象,而不是第一次访问得到内容的快照。

appendChild(node) //添加到childNodes末尾,返回添加的节点
removeChild(node) //返回被移除节点
replaceChild(new,old) //返回替换的节点
insertBefore(new,old) //返回插入的节点
cloneNode(flag) //flag决定是否深拷贝节点

原型和原型链

每个 JavaScript 对象都有一个原型对象。原型对象可以看做是对象的一个模板,包含了共享的属性和方法。

原型链(prototype chain)是指通过对象的原型对象来查找属性或方法的过程,即如果访问一个对象的属性或方法时,在该对象本身找不到,就会沿着原型链一直向上查找,直到找到该属性或方法或者到达原型链的顶部,即 Object.prototype。

作用域和作用域链

作用域决定了代码区中变量和其他资源的可见性。

分为全局作用域、函数作用域、块级作用域。

词法作用域,又叫静态作用域,变量被创建时就确定好了,而非执行阶段确定的。

当在Javascript中使用一个变量的时候,首先Javascript引擎会尝试在当前作用域下去寻找该变量,如果没找到,再到它的上层作用域寻找,以此类推直到找到该变量或是已经到了全局作用域。

可视区域判断

SVG用途

闭包

事务

JSON操作

判断数据类型

一、typeof

console.log("typeof null: "+ typeof null);
console.log("typeof undefined: " + typeof undefined);
console.log("typeof 1: " + typeof 1);
console.log("typeof 'str': " + typeof "str");
console.log("typeof true: " + typeof true);
console.log("typeof []: " + typeof []);
console.log("typeof {}: " + typeof {});
console.log("typeof function () {}: " + typeof function () {});

输出:

typeof null: object
typeof undefined: undefined
typeof 1: number
typeof 'str': string
typeof true: boolean
typeof []: object
typeof {}: object
typeof function () {}: function

结论:typeof不能判断对象,除了函数!

二、instanceof

instanceof能精准判断对象类型,但不能判断基本类型

console.log(null instanceof Object);//false
console.log(function(){} instanceof Function);//true
console.log(new Set() instanceof Set);//true
console.log(1 instanceof Number);//false

三、constructor

所有对象(使用 Object.create(null) 创建的对象除外)都将具有 constructor 属性。在没有显式使用构造函数的情况下,创建的对象(例如对象和数组文本)将具有 constructor 属性,这个属性指向该对象的基本对象构造函数类型。
---MDN

console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true

四、Object.prototype.toString.call()

生成器

Generator控制函数的启停。

function *foo(x) {
  let y = 2 * (yield (x + 1))
  let z = yield (y / 3)
  return (x + y + z)
}
let it = foo(5)
console.log(it.next())   // => {value: 6, done: false}
console.log(it.next(12)) // => {value: 8, done: false}
console.log(it.next(13)) // => {value: 42, done: true}
graph 调用Generator函数返回一个迭代器 --> 第一次调用next,忽略传参,返回表达式结果6--> 第二次调用next,传参12作为上一个yield返回结果,故y=24,返回8 --> 第三次调用next,传参13作为上一个yield返回结果,故z=13,返回42

可以通过Generator函数解决回调地狱。

字符串的排列组合

不重复字符串的组合

function getCombination(str){
    if(str.length === 1){
        return [str]
    }
    // 不包含首字母的各种切片
    let res1 = arguments.callee(str.slice(1));
    // 加上首字母的切片
    let res2 = res1.map(x => str[0]+x);
    // 只有首字母
    let res3 = [str[0]];
    // 合并
    return res3.concat(res1,res2);
}
console.log(getCombination("abc"));

不重复字符串的排列

function getPerputation(str){
  if(str.length===1) return [str];
  let res=[];
  // 包含除去第一个字符的各种排列
  let arr=arguments.callee(str.slice(1));
  for(let i=0;i<arr.length;i++){
    // 记录新排列
    let partArr=[];
    for(let j=0;j<arr[i].length+1;j++){
      // 切片与前一个字母的排列
      let newStr=arr[i].slice(0,j)+str[0]+arr[i].slice(j);
      // 存储新排列
      partArr.push(newStr);
    }
    // 将新排列数组合并到res
    res=res.concat(partArr);
  }
  return res;
}
console.log(getPerputation('abc'));

不重复字符串的排列组合

function getComAndPer(str){
  let comArr=getCombination(str);
  let res=[];
  for(let i of comArr){
    let perArr=getPerputation(i);
    res=res.concat(perArr);
  }
  return res;
}
console.log(getComAndPer('abc'));

解析URL的参数成对象格式

题目:/myurl?key0=&key1=val1&key2[]=0&key2[]=1#page1 解析返回 {“key0”:””, “key1”:”val1”, ”key2”:[“0”, “1”] } 的Object对象。

function parseURL(urlStr) {
  //去掉非查询参数部分
  let paramStr = urlStr.split("?")[1].split("#")[0];
  let urlObj = {};
  paramStr.split("&").forEach((item, index, arr) => {
    //匹配方括号
    if (item.match(/(\[\])/g)) {
      let keyValue = item.split("[]=");
      if (urlObj.hasOwnProperty(keyValue[0])) {
        urlObj[keyValue[0]].push(keyValue[1]);
      } else {
        urlObj[keyValue[0]] = [keyValue[1]];
      }
    } else {
      urlObj[item.split("=")[0]] = item.split("=")[1];
    }
  });

  return urlObj;
}

console.log(parseURL("/myurl?key0=&key1=val1&key2[]=0&key2[]=1#page1"));

超出范围的大整数相加

标签:obj,log,JavaScript,start,let,typeof,console,随笔
From: https://www.cnblogs.com/LiJunLin1231/p/17222122.html

相关文章

  • 代码随想录算法训练营第一天| javascript |二分查找_LeetCode704, 移除元素_LeetCode2
    二分查找题目链接:https://leetcode.cn/problems/binary-search/文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html视频讲解:ht......
  • 随笔分类里的JAVA一栏里面是有内容的!!!
    随笔分类里的JAVA一栏里面是有内容的!!!可能是网站有bug,没有显示出来,需要点击进去,然后在左栏就能看到有关JAVA的内容了。博客园在文件分栏应该这里有bug,比如点击最外层文件......
  • JavaScript删除URL指定的参数和值
    JavaScript删除URL指定的参数和值,不跳转(functionhandleLocationHref(){varurl=window.location.href;varparams=(window.location.search||'?').s......
  • <<高并发系统实战课>> 小记随笔 —— 用户中心案例优化
    案例介绍用户中心的主要功能是维护用户信息、用户权限和登录状态,它保存的数据大部分都属于读多写少的数据。常见的优化方式主要是将用户中心和业务彻底拆开,不再与业务耦......
  • 【JavaScript】44_DOM编程初步
    1、初识要使用DOM来操作网页,我们需要浏览器至少得先给我一个对象才能去完成各种操作所以浏览器已经为我们提供了一个document对象,它是一个全局变量可以直接使用document代表......
  • JavaScript
    变量:区分大小写,不把一个值保存到新的变量,这个变量就是一次性的(就是丢了这个数据地址)//驼峰命名var变量名;常量:不可改变的值用常量//全部单词大写,用_分割单词 数......
  • 人物速写随笔-重心
    通常重心线是第七节椎骨的垂直线 ......
  • JavaScript作用域闭包(你不知道的JavaScript)
    JavaScript闭包,是JS开发工程师必须深入了解的知识。3月份自己曾撰写博客《​​JavaScript闭包​​》,博客中只是简单阐述了闭包的工作过程和列举了几个示例,并没有去刨根问底,......
  • JavaScript词法作用域(你不知道的JavaScript)
    JavaScript并不是传统的块级作用域,而是函数作用域!一、作用域1.JavaScript引擎在代码执行前会对其进行编译,在这个过程中,像vara=2这样的声明会被分解成两个独立的步骤:......
  • 1.javaScript日期格式化转换
    //(newDate()).Format("yyyy-MM-ddhh:mm:ss.S")==>2006-07-0208:09:04.423Date.prototype.Format=function(fmt){varo={"M+":this.getMonth()+1,//mont......