首页
归档
友链
关于
壁纸
直播
Search
1
电脑开机主板 CPU 故障灯亮,无法正常开关机
193 阅读
2
破解 OpenWrite 微信导流
95 阅读
3
Windows11 5 月累计更新导致 .NET 无法使用
82 阅读
4
夏日小风扇,进来凉快一下叭!
67 阅读
5
解决 PowerShell 窗口闪烁,字体变化问题
62 阅读
站点
好玩
其他
读书笔记
开发
登录
Search
标签搜索
总结
读书笔记
小工具
好玩分享
windows
Typecho
云空调
云风扇
github
git
Nginx
Firewall-cmd
Frp
VSCode
PowerShell
PC
SSH
JMeter
cdn
XiaoLu
累计撰写
34
篇文章
累计收到
3
条评论
首页
栏目
站点
好玩
其他
读书笔记
开发
页面
归档
友链
关于
壁纸
直播
搜索到
10
篇与
的结果
2022-02-19
《JavaScript 学习指南》— 原型链
很久之前从《JavaScript 学习指南》上学习了原型链的知识,关键是理解和记住那个原型链的图,现在有些忘记了,复习一下!原型链图示我是倒着去理解原型链的,先根据原型链现有的状态(规则),逐步深入去刨析它们之间的关系。现有的状态是什么呢?从 《JavaScript 高级程序设计 v4》这本书上摘下来一句:{callout color="#3398e6"}每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型{/callout}拿下面这个图来看,Foo、Object、Function 是构造函数, 每个构造函数都有一个原型对象 (prototype),在图中用紫色文字箭头指示; 原型有一个属性指回构造函数 (constructor),在图中用绿色文字箭头指示; 实例有一个内部指针指向原型 (__proto__),在图中用褐色文字箭头指示。 显然,要搞清楚原型链,必须要了解 (__proto__),prototype,constructor。关于__proto__{message type="info" content="每个对象都有一个 (__proto__) 属性指向构造函数的 prototype"/}从对象开始,对象可不止是这样的:let obj = {};在 JavaScript 中,除了基本数据类型外,其他的一切都是对象。通过 function 关键字定义的函数、通过 let、const 声明的用花括号包裹的变量、通过 class 关键字定义的类,都可看作是对象。既然是对象(实例),它就会遵循原型链规则,内部有一个 (__proto__) 属性指向构造函数的原型。可以在上图中得到验证:图中共有 8 个 (__proto__),对应着 (f1 f2)、(o1 o2)、Foo、Object、Function 以及 3 个不同的 prototype。关于 prototype(原型){message type="info" content="只有函数才有且必然有 prototype"/}函数和对象是什么关系呢?函数就是对象,函数是对象的一个子集。因此,函数不仅有 prototype,还有 (__proto__),前者是其作为函数的特征,后者是其作为对象的特征。在上图中,三个函数 Foo、Object、Fucntion 都有 prototype,非函数类型的对象没有 prototype。函数能够通过 new 来构造自己的实例,就是把自己的 prototype 的引用交给了实例,使得实例能够通过__proto__属性来访问自己的原型。关于 constructor它存在于 prototype 中,是对构造函数的引用。构造函数能够通过 prototype 属性找到自己的原型,原型可以通过自己的 constructor 属性找到构造函数,这是一个双向的过程。通过构造函数创建了实例,那么实例便可通过__proto__找到构造函数。
2022年02月19日
11 阅读
0 评论
0 点赞
2022-02-18
《JavaScript 高级程序设计 v4》— 模块
CommonJS 规范NodeJS 模块系统使用了有轻微修改的 CommonJS 规范,浏览器不支持 CommonJS。CommonJS 规范使用 require() 指定依赖,使用 exports 对象 定义自己的 API。let fs = require("os"); module.exports = { platformInfo: fs.platform() }require()NodeJS require() 文档require() 可以导入 node_modules 目录中的文件, 可以导入 json 文件 ,可以导入自定义的 js 文件,可以导入内置核心模块:require("os"); require("./api.js") // 可以不带后缀名 require("axios"); require("./config.json");require 要不要赋值给变量?require() 一个模块时,会 执行 里面的内容。所以要不要将 require() 赋值给变量,关键就是看 require() 有没有返回值,如果有返回值就把它赋值给变量,后面用得到。但是如果是一次性加载这个模块,不管它有没有返回值,以后不用了,那么也没有必要把它赋值给变量。多次 require 相同模块会怎样?require() 只会加载模块一次,然后把它放进缓存中,再遇到相同的模块不会加载了。比如在一个文件 A 里写了循环 10 次输出 hello world,在另外一个文件 B 里 require(A) 写了 100 次,最终仍是输出 hello world 10 次。上面提到的缓存实际上是 require.cache,这是一个保存着已经加载的模块的对象,如果把这个对象中关于某个已加载模块 C 的键值对删除,下次遇到 require(C) 时仍会加载。IIFE (immediately invoked function expression)IIFE 可以实现模块的类似功能,既隐藏了内部实现细节,又可以返回供其他模块调用的 API。let moduleA = (function(){ return something; })();
2022年02月18日
8 阅读
0 评论
0 点赞
2022-02-16
《ES6标准入门》—【字符串、数值扩展】
字符的 unicode 表示法:我觉得这个东西用的不多,因此用折叠面板把它包裹起来,用到的时候再来打开查看:{collapse}{collapse-item label="详细内容"} 在 JS 中,可以用 \uxxxx 的形式表示字符,有些字符是可见的打印字符,有些字符是不可见的控制字符。JS 的局限性在于,只能表示 \u0000-\uFFFF 之间的字符,超出此范围的要用两个双字节的形式 (UTF-16) 呈现:"\uD842\uDFB7" // '𠮷' "\u20BB7" // '₻7'ES6 的改进是,可以用花括号包裹起来的形式表达:"\u{20BB7}" // '𠮷'一些示例:'\z' === 'z' '\172' === 'z' '\x7A' === 'z' '\u007A' === 'z' '\u{7A}' === 'z'{/collapse-item}{/collapse}字符串新增方法{message type="info" content="emmm, 关于字符处理的那些方法没写,平时也没见过用过,比如 String.raw(),String.codePointAt() 之类的"/}{card-list}{card-list-item} includes ( str ) 主串是否包含字串{/card-list-item}{card-list-item} startsWith ( str ) 主串是否以字串开头{/card-list-item}{card-list-item} endsWith ( str ) 主串是否以字串结尾{/card-list-item}{/card-list}此外,这三个方法可支持第二个参数,用以设置搜索的 起始位置 {card-list}{card-list-item} repeat ( n )返回一个新字符串,将原串重复 n 次{/card-list-item}{card-list-item} padStart ( length, str ) 返回一个新字符串,用 str 补全原串直到长度为 length,从前往后补{/card-list-item}{card-list-item} padEnd ( length, str ) 返回一个新字符串,用 str 补全原串直到长度为 length,从后往前补{/card-list-item}{/card-list}模板字符串有了模板字符串,不再需要 + 号来连接字符串和变量,而是将变量放在 ${} 中。这个特性已经非常熟悉了,示例如下:let str = "old"; let str_1 = `how ${str} are you`; console.log(str_1); // how old are you对于 ${} 这个神奇的语法,花括号内还可以填入表达式,写点简单的 html 的东西简直不要太爽:$('#result').append( `There are <b>$(basket.count)</b> items in your basket, <em>$(basket.onSale)</em> are on sale!`)此外,模板字符串可以嵌套模板字符串,还有一个叫做标签模板的功能。下面的代码就是标签模板的示例,我来仔细阐述一下含义:首先它的语法格式是:functionName``,前面是已经定义好的函数的名字,然后紧跟两个重音符,它实际上是相对于 functionName(params) 的变体。那么这个参数怎么传呢?打印 arguments 的结果如下:{alert type="info"}0: (3) ['The total is ', ' (', ' with tax', raw: Array(3)]1: 302: 31.5{/alert}第一个参数是用 ${} 分割成的字符串数组,这些字符串都是静态的不变的第二个及后面的诸多参数,都是 ${} 括号内的变量let total = 30; let msg = passthru`The total is ${total} (${total*1.05} with tax`; function passthru(literals) { console.log(arguments); let result = ''; let i = 0; while (i < literals.length) { result += literals[i++]; if (i < literals.length) { result += arguments[i] } } return result; } msg // "The total is 30 (31.5 with tax)"弄懂了这些,上面的代码就不难理解了,每次从静态字符串数组和动态变量组 (arguments 是类似数组,却不是数组,只不过具有 iterable 接口而已) 各取一个然后拼接在一起,最后把结果返回。{dotted startColor="#e44e4e" endColor="#3ea2e0"/}数值的扩展{card-list}{card-list-item} Number.isFinite() 检查一个数值是否是有限的 返回 true:NaN,Infinity,'10',true,-Infinity,'foo' 返回 false:100,1.5{/card-list-item}{card-list-item} Number.isNaN() 检查一个值是否是 NaN 返回 true:NaN,0/0,'true'/0,'abc'/'ccc' 返回 false:10,'15',true,{/card-list-item}{/card-list}{callout color="#4d43d6"}必须说明 :上面两个方法先判断类型是不是数值,如果不是返回 false,然后再判断是不是 NaN,这也是 Number 下这两个方法和 window 下的两个方法的区别。{/callout}{card-list}{card-list-item} Number.parseInt() 将输入值转换为整数{/card-list-item}{card-list-item} Number.parseFloat() 将输入值转换为浮点数{/card-list-item}{/card-list}{callout color="#df5d7e"} 必须说明: 上面两个方法和全局 window 下的两个方法完全一致,window.parseInt === Number.parseInt 的值是 true{/callout}{card-list}{card-list-item} Number.isInteger() 判断一个值是否是整数,输入类型必须是 Number,否则返回 false 返回 true:25,25.0, 返回 false:25.1,'15',true{/card-list-item}{card-list-item} Number.EPSILON 这是一个极小值,因为浮点运算是有误差的,如 0.1 + 0.2 !== 0.3。因此,如果运算结果和预期结果的差值小于此极小值,那么认为运算是合理的。{/card-list-item}{card-list-item} Number.isSafeInteger() JS 能够表示的整数范围的绝对值 < 2^53,超过范围就无法精确求值了,如:Math.pow(2, 53) === Math.pow(2, 53) + 1 返回的是 true。ES6 引入 Number.MAX_SAFE_INTEGER 和 Number.MIN_SAFE_INTEGER 来表示上下限,同时使用 Number.isSafeInteger() 来判断是否是在有效值区间内。{/card-list-item}{/card-list}
2022年02月16日
20 阅读
0 评论
0 点赞
2022-02-14
《JavaScript重难点实例精讲》— ES7 +
马上写
2022年02月14日
13 阅读
0 评论
0 点赞
2022-02-14
《ES6标准入门》—【let const 解构赋值】
2015 年正式发布的 ES6 至今 7 年了,然而保留 ES5 习惯的人还是很多,好好看书好好学习本文结合了阮一峰《ES6标准入门》第 2 版let 和 const 命令{anote icon="fa-plane" href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/block" type="secondary" content="块语句 MDN"/}被 { } 包裹起来的称为块语句,用于把语句组合起来,比如常见的 for 循环,如果不加 { } 只有一行代码会进入循环 (开端 粉丝狂喜 😯 ),加上了花括号后,多行代码会一起进入循环💧 块语句是有块级作用域的,但 let 和 const 有块级作用域,var 声明的变量是没有的:{{{ var a = 100 }}}f a // 100 {let a = 100}; a // ReferenceError: a is not defined💧 let 和 const 没有变量提升a // undefined b // ReferenceError: b is not defined var a = 100; let b = 200;💧 let 和 const 的暂时性死区:在变量声明之前,任何对变量的引用都是非法的,变量不可用{ a = 100; // Cannot access 'a' before initialization let a; }💧 不允许重复声明,包括函数参数变量的声明,块内变量的声明等function compute(arg) { let arg; // SyntaxError: Identifier 'arg' has already been declared }💧 块级作用域可替代 IIFE 立即执行函数,块内的细节对外隐藏{ // do something } (function () { // do something })();💧 与顶层对象脱钩,var 声明的对象会被添加到 window 中,let 和 const 的不会var a = 100; this.a // 100 window.a // 100 let b = 200; window.b // undefined this.b // undefined💧 块级作用域内声明函数ES5 规定函数只能在顶层作用域和函数作用域中声明,不能在块级作用域中声明,ES6引入了块级作用域,明确允许在块级作用域之中声明函数。emmm,具体的内容很多,不过我觉得不是特别重要,笔试面试应该考不到,而且浏览器并没有按照上面的规定实现,具体就看 图一,图二 吧关于 const 命令上面的内容对于 let 和 const 都是相同的,但是有些关于 const 的细节容易被忽视:const 只是保证变量名指向的地址不变,但 不保证其数据不变 ,基础数据类型的变量是不变的,引用数据类型的变量是可变的。对于数组类型,其各个内部函数都不影响使用const a = 100; a = 200; // TypeError: Assignment to constant variable. const student = {}; student.age = 20; // 正常 const students = []; students.push({}); // 正常const 声明的变量必须在声明时就赋值const c; // SyntaxError: Missing initializer in const declaration关于变量声明ES5 可以使用 var 和 function,ES6 可以使用 let 和 const,以及 import 和 class,加起来一共 6 种变量声明方式{dotted startColor="#ff6c6c" endColor="#1989fa"/}数组解构赋值let [a, b, c] = [1, 2, 3]; let [foo, [[bar], baz]] = [1, [[2], 3]]; let [ , , third] = ["foo", "bar", "baz"]; // third: "baz" let [head, ...tail] = [1, 2, 3, 4]; // head: 1, tail: [2, 3, 4] let [x, y, ...z] = ['a']; // x: 'a', y: undefined, z: []上面的例子仅仅展示了等号右面是数组的情况,事实上,只要等号右面的对象具有 Iterator 接口,就可以用数组的形式被结构赋值,如:后面笔记里会提到的 Set,DOM 中的 HTMLCollection,NodeList 等,再举一个 Generator 的例子:{callout color="#905cf0"}Generator 是 ES6 提出的,原生具有 Iterator 接口,特征是 function* 和 yield {/callout}// 用 ES6 Generator 来计算斐波那契数列 function* fibs() { var a = 0; var b = 0; while(true) { yield a; [a, b] = [b, a + b]; } }解构赋值允许指定 默认值 ,当没有显式为变量赋值时,变量使用给定的默认值。对于下面的例子,因为 x 没有成功解构到任何有效值,因此 x 被赋予默认值 1。 注意 :当且仅当被解构的位置是 undefined 时,才会使用默认值,这里是 严格相等 的判断。let [x = 1] = []; let [y = 2] = [null]; x // 1 y // null 而不是 2, null 并不严格相等于 undefined另外一个需要注意的地方是解构赋值的顺序,是先判断被解构的位置是否是 undefined,然后根据结果来决定要不要使用默认值。这意味着,如果默认值是一个表达式,这个表达式就是惰性的,只有用到的时候才会被调用求值:function com() { console.log('called me'); return 'OK'; } let [x = com()] = [1]; // com 并不会被调用还有一个特性是,在解构赋值表达式中,等号左边变量的默认值可以引用其他变量,前提是被引用的变量已经声明过了。emmm,我是觉得这个特性还是很绕的,影响可读性?反正我不用 😢let [x = 1, y = x] = []; // x: 1, y: 1 let [x = 1, y = x] = [2]; // x: 2, y: 2 let [x = y, y = 1] = []; // ReferenceError: y is not defined{dotted startColor="#ff6c6c" endColor="#1989fa"/}对象解构赋值数组的结构赋值结果和 元素在数组中的 排列次序 有关,而对象的解构赋值结果是和变量名相关的,与次序无关。{message type="info" content="变量名必须严格相等才能解构赋值成功"/}let {name, age} = {age: 10, name: 'XiaoLu'}; // name: 'XiaoLu', age: 10 let {phone} = {age: 10, name: 'XiaoLu'}; // phone: undefined💧 如果想要变量名不相等,如经常会出现前后端变量名命名格式不一致问题,前端习惯全部小写以下划线间隔,而调用某个 API 接口后返回的是驼峰式的命名,必须使用下面的写法:{callout color="#ea6695"} 以前真不知道还能这么玩,太喜欢了!😜 {/callout}let {studentName: student_name} = {studentName: 'xiaolu'}; // student_name: 'xiaolu' // studentName: ReferenceError: studentName is not defined💧 另外,对象解构赋值也支持嵌套形势。其实,坦白的说,能够想到的形式,应该都是支持的,比如对象解构赋值中再嵌套数组的解构赋值:let {nums: [a] } = {nums: [1, 2 , 3]} a // 1💧 不过我觉得还是以 代码可读性 为首要原则,技巧再高超的代码让人看不懂也是不行的。比如书上为了说明给了这样的样例代码,一时半会儿是看不懂是把哪些值赋给了哪些变量。因为这里面 p 是模式,x 和 y 才是变量。var obj = { p: [ 'Hello', {y: 'World'} ] }; var {p: [x, {y}]} = obj;💧 对象的解构可以指定默认值,主要是后两种不常见:let {x = 3} = {} // x: 3 let {x, y = 5} = {x: 1} // x: 1, y: 5 let {x: y = 3} = {} // y: 3 let {x: y = 3} = {x: 5} // y: 5{alert type="error"}容易出错的地方:对象的解构赋值一定要双方结构互相对应,否则会出错,比如:let {foo: {bar}} = {baz: 'baz'}; // ypeError: Cannot read properties of undefined (reading 'bar')因为与 foo 对应的属性在右侧找不到,因此相当于把 undefined 解构到 {bar} 中,相当于调用 undefined.bar, 这显然是不合理的。将一个已经声明的变量用于解构赋值,要使用圆括号包裹:let x; { x } = {x: 1}; // SyntaxError: Unexpected token '='JS 会认为 { x } 是可执行的代码块,显然语法错误,正确的做法是:let x; ({ x } = {x: 1});{/alert}
2022年02月14日
13 阅读
0 评论
0 点赞
1
2