URI: Uniform Resource Identifier 指的是统一资源标识符
URL: Uniform Resource Location 指的是统一资源定位符
URN: Universal Resource Name 指的是统一资源名称
URI 指的是统一资源标识符,用唯一的标识来确定一个资源,它是一种抽象的定义,也就是说, 不管使用什么方法来定义,只要能唯一的标识一个资源,就可以称为 URI。
URL 指的是统一资源定位符,URN 指的是统一资源名称。URL 和 URN 是 URI 的子集,URL 可 以理解为使用地址来标识资源,URN 可以理解为使用名称来标识资源。
module.exports = {}、exports.xxx = 'xxx'require(./index.js)require 得到的值是值的拷贝,即你引用其他 JS 文件的变量,修改操作了也不会影响其他文件CommonJS 规范中模块是同步加载的,即在 index.js 中加载 index2.js,如果 index2.js 卡住了,那就要等很久。index.html 中做 var index = require('./index.js') 操作报错,因为它最终是后台执行的,只能是 index.js 引用 index2.js 这种方式。Asynchronous Module Definition 的缩写执行时机的处理不同**,二者皆为异步加载模块;import './index'import { a } from './index.js'import { a as jsliang } from './index.js'import * as index from './index.js'export aexport { a }export { a as jsliang }export default function() {}export 命令和 import 命令可以出现在模块的任何位置,只要处于模块顶层就可以。 如果处于块级作用域内,就会报错,这是因为处于条件代码块之中,就没法做静态优化了,违背了 ES6 模块的设计初衷。import 命令具有提升效果,会提升到整个模块的头部,首先执行。CommonJS 区别:
CommonJS 模块是运行时加载,ES6 Modules 是编译时输出接口CommonJS 输出是值的拷贝;ES6 Modules 输出的是值的引用,被输出模块的内部的改变会影响引用的改变CommonJs 导入的模块路径可以是一个表达式,因为它使用的是require() 方法;而 ES6 Modules 只能是字符串CommonJS this 指向当前模块,ES6 Modules 的 this 指向 undefinedES6 Modules 中没有这些顶层变量:arguments、require、module、exports、__filename、__dirname原理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oHVvAzKl-1661952053815)(%E9%9D%A2%E8%AF%95%E5%87%86%E5%A4%87%2064d3ed4453ae44a38f71e8b99d75fcc4/Untitled%203.png)]
@babel/traverse(遍历)方法维护这AST树的整体状态,并且可完成对其的替换,删除或者增加节点,这个方法的参数为原始AST和自定义的转换规则,返回结果为转换后的AST。浅克隆之所以被称为浅克隆,是因为对象只会被克隆最外部的一层,至于更深层的对象,则依然是通过引用指向同一块堆内存。浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;
深拷贝是拷贝多层,每一级别的数据都会拷贝出来;
总结来看,浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值那种,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么对于浅拷贝而言就只能拷贝其引用,对象的改变会反应到拷贝对象上;浅拷贝就是拷贝了一层,除了对象是拷贝的引用类型,其他都是直接将值传递,有自己的内存空间的。
但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。
浅拷贝方式:
var cloneObj1= Object.assign({}, obj1);深拷贝方法
使用 Object.create()方法,var newObj = Object.create(oldObj)
转成 JSON 再转回来
var obj2 = JSON.parse(JSON.stringify(obj1));console.log(obj1 === obj2);// falseconsole.log(obj1.body === obj2.body);// falsevar obj1 = { fun: function(){ console.log(123) } };var obj2 = JSON.parse(JSON.stringify(obj1));console.log(typeof obj1.fun);// 'function'console.log(typeof obj2.fun);// 'undefined' <-- 没复制递归拷贝
var array = [
{ number: 1 }, { number: 2 }, { number: 3 }
];
function copy (obj) {
var newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
}
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ? copy(obj[i]) : obj[i];
}
return newobj
}
var copyArray = copy(array)
copyArray[0].number = 100;
console.log(array); // [{number: 1}, { number: 2 }, { number: 3 }]
console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
数组深拷贝
var array = [1, 2, 3, 4];var copyArray = array.slice();var copyArray = array.concat();arrayObject.concat(arrayX,arrayX,......,arrayX)方法用于连接两个或多个数组,返回一个新的数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。例如arr1.concat(arr2,arr3),把arr1,arr2,arr3拼接起来。arguments 是属于函数内部的变量,其值是函数参数列表,一个类数组对象,是具有长度属性的,却并不是数组。不具备slice()这个方法,那就意味着 arguments.slice()行不通。
var args = [].slice.call(arguments);
通过[]创建一个空数组,通过slice方法从已有的数组中返回选定的元素。
然后他通过call()方法强制指定当前函数方法内部变量arguments,返回了函数参数列表,这个时候slice()方法将其解析,因为没有给slice参数start和end,所以直接返回从0到最后一个位置的所有参数,将这些参数内部push到[]这个创建好的空数组中,这样子就返回了一个数组元素!
!important > 行内样式>ID选择器 > class选择器 > 标签 > 通配符 > 继承 > 浏览器默认属性
link和@import的区别link 是 XHTML 标签,除了加载 CSS 外,还可以定义 RSS 等其他事务;@import 属于 CSS 范畴,只能加载 CSS。link 引用 CSS 时,在页面载入时同时加载;@import 需要页面网页完全载入以后加载。link 是 XHTML 标签,无兼容问题;@import 是在 CSS2.1 提出的,低版本的浏览器不支持。link 支持使用 Javascript 控制 DOM 去改变样式;而 @import 不支持。分块处理,然后再合并起来
将100万分成100份,每份1万个数,取出每1万个数中前100个最大的数,再将这100份合并起来,取出前100个最大的数
利用快排的思想,首先选择一个基数n[0],小的放前面,大的放后面,分成[a,b)b(b,d],递归,直到最右边的区间个数小于100个,不用管[a,b)。返回长度小于等于100的(b,d]区间,再返回一层一层去找的[a,b),取出剩下的,直到数量达到100.
0.30000000000000004,JavaScript 遵循 IEEE 754 规范。
在 JavaScript 中,所有的 Number 都是以 64-bit 的双精度浮点数存储的; 双精度的浮点数在这 64 位上划分为 3 段,而这 3 段也就确定了一个浮点数的值,64bit 的划分是“1-11-52”的模式,具体来说:
1.就是 1 位最高位(最左边那一位)表示符号位,0 表示正,1 表示负;
2.11 位表示指数部分;
3.52 位表示尾数部分,也就是有效域部分
由于只能存储52位尾数位,所以会出现精度缺失,把它存到内存中再取出来转换成十进制就不是原来的0.1了,就变成了0.100000000000000005551115123126,而为什么02+0.1是因为
// 0.1 和 0.2 都转化成二进制后再进行运算 0.00011001100110011001100110011001100110011001100110011010 + 0.0011001100110011001100110011001100110011001100110011010 = 0.0100110011001100110011001100110011001100110011001100111
// 转成十进制正好是 0.30000000000000004
/**
** 加法函数,用来得到精确的加法结果
** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
** 调用:accAdd(arg1,arg2)
** 返回值:arg1加上arg2的精确结果
**/
function accAdd(arg1, arg2) {
var r1, r2, m, c;
try {
r1 = arg1.toString().split(".")[1].length;
} catch (e) {
r1 = 0;
}
try {
r2 = arg2.toString().split(".")[1].length;
} catch (e) {
r2 = 0;
}
c = Math.abs(r1 - r2);
m = Math.pow(10, Math.max(r1, r2));
if (c > 0) {
var cm = Math.pow(10, c);
if (r1 > r2) {
arg1 = Number(arg1.toString().replace(".", ""));
arg2 = Number(arg2.toString().replace(".", "")) * cm;
} else {
arg1 = Number(arg1.toString().replace(".", "")) * cm;
arg2 = Number(arg2.toString().replace(".", ""));
}
} else {
arg1 = Number(arg1.toString().replace(".", ""));
arg2 = Number(arg2.toString().replace(".", ""));
}
return (arg1 + arg2) / m;
}
//给Number类型增加一个add方法,调用起来更加方便。
Number.prototype.add = function(arg) {
return accAdd(arg, this);
};
// 0.2 和 0.3 都转化为二进制后再进行计算 0.001100110011001100110011001100110011001100110011001101 + 0.0100110011001100110011001100110011001100110011001101 = 0.10000000000000000000000000000000000000000000000000001 //尾数为大于52位
// 而实际取值只取52位尾数位,就变成了 0.1000000000000000000000000000000000000000000000000000 //0.5
0.2 和0.3分别转换为二进制进行计算:在内存中,它们的尾数位都是等于52位的,而他们相加必定大于52位,而他们相加又恰巧前52位尾数都是0,截取后恰好是0.1000000000000000000000000000000000000000000000000000也就是0.5