【JavaScript 】严格模式,With关键字,测试框架介绍,assert
❤️ Author: 老九
☕️ 个人博客:老九的CSDN博客
🙏 个人名言:不可控之事 乐观面对
😍 系列专栏:
文章目录
- 静态类型语言
- 弱类型
- 严格模式
- 将过失错误转化为异常
- 简化变量的使用
- With
- 测试框架
- try-catch
- 选择性捕获
- Assert断言
静态类型语言
- 在js中,变量是没有类型的,但值是有类型的;js语言属于动态类型的语言,变量有类型的属于静态类型语言:c,c++,java,TypeScript
- 其中的ts是比较重要的,在静态类型语言里,一个数组里只能放同一种类型的值
var a1: number[] = [1, 2, 32, 4]
var x = a1[2]
var a : number = 8
var b: string = 'fdsf'
var c: boolean = true
var d: bigint = 8n
var e: symbol = Symbol()
var f: null = null
var g: undefined = undefinedvar xx: any = 12
xx = 'woeif'
xx = []
xx = {}var ff: (a: string, b: number) => boolean =function (a,b){return true}//函数类型是参数类型和返回值类型的总和
function foo(a: number = 2, b: string , ...args : number[]) : number{return 1
}var age1: number | string | bigint = 8
//联合类型
type Age = number | string | bigint
var age : Age[] = [8,'fdsff',8n]type 坐标 = {x : number,y: number,//返回一个函数,不接参,但是返回数字length : () => number,
}
var obj: 坐标 = { x: 1, y: 2 ,length() {return Math.sqrt(this.x ** 2 + this.y ** 2)
}}
//和type一样的作用,没有等号了,还有一些细微的差别
interface 位置{x : number,y : number
}
弱类型
- 从是否会发生自动类型转换的角度分类:强类型和弱类型
强类型:不会发生自动类型转换 python
弱类型:会发生自动类型转换:js c
严格模式
- 在一个文件或者函数的顶部写"use strict"
- 在严格模式中,不事先声明变量就使用的话会报错;其次如果在一个函数中,加了”use strict"字符串,这个函数不被当作构造函数的时候(或者说没有加new的时候),函数调用this是undefined,而在非严格模式下,此种情况this指向全局作用域对象(如window)
function ceshi1() {"use strict";console.log(this);}function ceshi2() {console.log(this);}
<script>function ListNode(val){//if(!(this instanceof ListNode))//当一个函数被new调用时,函数内的特殊表达式new.target指向函数自身//当不被new调用时,new.target指向nullif(new.target !== ListNode){//没加new调用return new ListNode(val)}this.val = val}
</script>
- 其次禁止了给一个函数多个相同的参数
- 注意严格模式在下面这种情况下,上下是两个文件,foo函数内部是没有采用严格模式的
将过失错误转化为异常
- 1.严格模式下无法再创建全局变量
- 2.严格模式会引起静默失败(不报错也没有任何效果的赋值会抛出异常),通常情况下给NaN赋值没有任何效果(NaN是一个不可写的全局变量(Undefined也是)),但如果在严格模式下给NaN赋值会抛出异常
补充:const,这个是定义一个常量,我们是无法给常量赋值的,例如:const a = {x:2,y:3},我们不能写a = 2,但是我们可以让a里面的属性改变,例如a.x++,这时候a = {x:3,y:3},如果我们想让这个对象里面的属性也无法改变,就用Object.freeze(a),把对象冻结就可以了。但这样只是a对象的属性不能改动了,如果a对象中的属性指向了别的对象,别的对象也是可以修改的,如果让他们都不能修改,需要递归调用freeze
上面那个判断是用来判断有没有被冻结过,如果这个对象的指向构成一个环状的话,就会无限递归了。
- 3.不能删除不可删除的属性
- 4.参数名唯一
- 5.不支持8进制(0b:2进制,0x16进制,0o8进制),八进制有两种写法,第二种八进制的写法是不行的
简化变量的使用
- 1.严格模式禁用with,使用with会让代码在运行时候无法得知运行顺序
With
- With接受一个对象,如果With函数中使用了没有创建过的变量,就会在WIth函数接受的参数的对象中找没有对应的值,如果还是没有,就再在函数外面找,相当于改变了参数的作用域
- 严格模式的代码不能使用with语句
- 2.eval不会再为上层范围(全局)引入新变量(全局变量),eval里面接受一个字符串,把字符串当代码执行
- eval不是一个普通的函数,它可以读到调用eval函数的函数的变量,会影响函数的封闭性,因此在严格模式中是无法读取上层范围的变量的。
- eval的特殊性,eval2是调用的全局的变量,eval是调用的当前函数的
3.在js中arguments和形参是绑定的
使用严格模式之后,就不会影响了
4.在严格模式下,callee会报错,arguments.callee就是调用了f函数本身,但是我们一般都直接写函数名调用函数自身就可以了。
5.js默认情况下,函数会把call函数传入的this,包装成一个对象,如图
如果我们把函数设置为严格模式,就不会包装成对象了
测试框架
- 测试代码一般都是重复的代码,我们有专门的软件设计了专门的语言来帮你做这些事情,只要指定想要的测试内容,他们会告诉你详尽的信息
- 这些软件就是测试框架,著名的测试框架有mocha,tape,jasmine
- mocha里面有两个函数,describe/it ,describe是用来区分要测试哪个模块,每一个具体的测试,要调用it
- 然后在git bash中输入mocha my-map.test.js,它会自动扫描以.test.js结尾的文件,并运行它
class Map3 {#keys = [] // private class field#vals = []constructor(entries = []) {for (var [key, val] of entries) {this.set(key, val)}}#keyIndex(key) {return this.#keys.indexOf(key)}forEach(action) {for (var i = 0; i < this.#keys.length; i++) {var key = this.#keys[i]var val = this.#vals[i]action(val, key, this)}}[Symbol.iterator]() {var i = 0return {next: () => {var key = this.#keys[i]var val = this.#vals[i]var entry = [key, val]i++return {value: entry,done: i > this.size}}}}get(key) {var keyIdx = this.#keyIndex(key)if (keyIdx >= 0) {return this.#vals[keyIdx]}}has(key) { // 判断映射中是否存在某个key的映射var keyIdx = this.#keys.indexOf(key)if (keyIdx >= 0) {return true}return false}set(key, val) { // 设置key的映射目标为valvar keyIdx = this.#keys.indexOf(key)if (keyIdx >= 0) {this.#vals[keyIdx] = val} else {this.#keys.push(key)this.#vals.push(val)}return this}delete(key) { // 删除key的映射对var keyIdx = this.#keys.indexOf(key)if (keyIdx >= 0) {this.#keys.splice(keyIdx, 1)this.#vals.splice(keyIdx, 1)return true}return false}clear() { // 清空所有的映射this.#keys = []this.#vals = []}get size() { // 返回当前Map中映射对的数量return this.#keys.length}
}module.exports = Map3
测试代码
const MyMap = require('./my-map.js')// describe / it// 如何执行:
// winpty mocha.cmd my-map.test.js
// mocha my-map.test.jsfunction assert(e, msg = 'error') {if (!e) {throw msg}
}// function assert2(e, msg = 'error') {
// if (!e) {
// return new Error(msg)
// }
// }describe('MyMap', () => {describe('constructor', () => {it('不传参的时候应该创建空映射', () => {var m = new MyMap()assert(m.size == 0)assert(m instanceof MyMap)assert(m instanceof MyMap)assert(m instanceof MyMap)assert(m instanceof MyMap)})it('传入二维表示初始值时能创建出非空映射', () => {var m = new MyMap([[1, 2], [2, NaN], ['foo', 'bar']])assert(m instanceof MyMap)})})describe('methods', () => {it('#set(key, val)', () => {var m = new MyMap()m.set(1, 2)var v = m.get(1)assert(v == 2)})it('#get(key, val)', () => {var m = new MyMap()m.set(1, 2)var v = m.get(1)assert(v == 2)})it('#get(key, val) with NaN', () => {var m = new MyMap()m.set(NaN, 2)var v = m.get(NaN)assert(v == 2)})})
})describe('MySet', () => {})
try-catch
- 当一个函数出现错误无法继续前行,立马停止执行并通过catch捕获,try-catch可以让发生错误的代码,抛出一个异常,异常本身也由一个值来表示,最极端的情况我们可以实现跳到调用栈的最外层,把调用栈中间的函数全都挂掉了。
- try-catch就像一个网兜一样,兜住这个错误。不然的话就有可能跳到最外层的调用栈,从而把中间的函数都略过了。
- 报错的时候,最下面那个at < anonymous > :1:5,at后面跟的是调用栈,anonymous是匿名函数,1是第一行,5是第五列
- error对象有一个message属性,还有个stack属性,这两个都是返回的字符串
选择性捕获
- try,catch,finally:无论发生什么,都运行finally里面的代码。
- throw是抛到离他最近的外层try包含框兜住。
- 当一个异常直到栈底都没被catch住,异常将会被环境(浏览器)捕获
- 可以给我们的代码创建一个新的错误类型,throw是抛出一个异常,然后后面的那个catch里面可以通过instanceof判断报错类型,像java里面的catch很多类型。
如果要自定义异常的话,需要使用继承
- try-catch练习,让调用这个函数永远不会发生错误
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8" /><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title><script>class MutiplicatorUnitFailure extends Error {}function primitiveMultiply(a, b) {if (Math.random() > 0.5) {return a * b;} else {throw new MutiplicatorUnitFailure("Multiplicator unit failure,please try again");}}//TODOfunction multiply(a, b) {try {var result = primitiveMultiply(a, b);return result;} catch (e) {if (e instanceof MutiplicatorUnitFailure) {return multiply(a, b);} else {throw e;}}}</script></head><body></body>
</html>
Assert断言
- 简言之,断言就是如果ok,就什么也不做,如果不ok们就直接抛错
- 断言能保重错误直接产生失败挂掉,让错误更早的暴露出来,避免在程序其他地方产生麻烦。
function assert(expr, message) {if (!expr) {throw new Error(message);}}function add(a, b) {assert(typeof a === "number",'a must be a number');}
————————————————————————
♥♥♥码字不易,大家的支持就是我坚持下去的动力♥♥♥
版权声明:本文为CSDN博主「亚太地区百大最帅面孔第101名」的原创文章