原生JS查疑补漏
文章目录
1. 分号
- 通常语句不添加
;
也可以正常运行,是因为JS默认将每一行的换行符理解为分号 - 而有一些必须添加
alert("1"); //这里的;不可缺少,否则将理解为一行语句;
[1,2].forEach(alert);
2. 注释
- 不支持注释嵌套
3. 严格模式/现代模式
- “use strict” 将启用最新的规则
- 必须放在脚本的最上面
classes
和modules
会默认使用该模式- 模式下变量必须先声明再使用
4. let
- let声明的变量作用域在其声明语句之后。
- 小心暂时性死区
- 声明变量的时候会绑定所在控件,控件会清空同名全局变量的影响。
5. 数据类型
5.1 Number
1/0
=>InfinityNaN
=>一个不正确的表达式。- number类型区间-(253-1)~(253-1)
- 超出使用bigInt,Safari/IE都不支持
//以n结尾
bigInt=121111111111111111111111111111111111111111111111n;
5.2 String
- 可以使用
反引号`
- 使用反引号之后就可以直接进行变量/常量/表达式引用了
let str ="kelasi"
alert(`geyou say niubi${str}`); //"geyou say niubikelasi"
感觉就是把jQuery的东西直接拿来用了,应该是ES6的新东西把,要么就是我之前学的时候不仔细漏掉了 逃
5.3 symbol
??? 是ES6的新东西把? 学过之后填坑。
6 类型转换
6.1 转数字类型
+
一元运算符- Nmuber()函数
- undefined => NaN
- null => 0
- true/false => 1/0
6.2 转boolean
- 非空为true 空为false
bool=Boolean("0") //bool = true
7 运算符
==
当两侧类型不同时先将两侧变量转化为数值型再进行比较。
"213"==true ; //false
"1" == true ; //true
- 使用<、>、<=、>=时
- null => 0
- undefined => NaN
===
不会对两边进行类型转换。&&
比||
级别高??
运算符:取元中第一个已定义的元。??
禁止和&&、||
一起使用。加括号分离后可用
8 switch
- case和arg 的比较是使用
===
进行的
9 函数
函数命名
- 通过对行为的描述
- show…
- get…
- calc…
- create…
- check…
- 不要再函数内进行多余的操作(createTable()就应当只创建Table而不是做多余的操作);
函数表达式&函数声明
//函数声明
function sum(a,b){
return a+b;
}
//函数表达式
let sum =function(a,b){
return a+b;
};
区别在于:函数创建的时间
10 测试
BDD行为驱动测试开发
- 测试
- 文档 告诉我们测试做了什么
- 案例 作为案例来展示函数应该怎样使用
10.1 库
- Mocha
<head>
<script src = "https://cdnjs.cloudflare.come/ajax/libs/mocha/3.2.0/mocha.js"></script>
<script>
mocha.setup("bdd");
</script>
</head>
<body>
...
<div id = "mocha"></div>
<script src = "test.js"></script>
<script>
mocha.run();
</script>
</body>
- Chai
<head>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/chai/3.5.0/chai.js"></script>
<script>
let assert=chai.assert;
</script>
</head>
完整的断言列表见chaidoc
- Sinon
10.2 描述文件
//test.js文件
describe("title",function(){
it("描述部分",function(){
//断言部分
assert.equal(arg1,arg2);
})
});
- 可以通过嵌套describe来进行测试分组
- before/after
- beforeEach/afterEach
11 对象Object
11.1属性
声明
const
不能重新赋值但可以修改- 对象属性常量方法见后
行属性调用
声明缩写
function makeUser(name,age){
return{
name:name,
age:age,
// 其他属性
};
}
let user= makeUser("John",30);
当出现上面这种属性名和变量名一样,通过变量生成属性的场景,可以使用缩写
function makeUser(name,age){
return{
name,
age,
...
};
}
甚至 我们可以这样使用
let user={
name,
age:30,
};
使用
- 推荐使用
object[属性名]
进
属性的命名
- 与变量名不同的是,属性名称使用保留字并不会报错。
- 无论属性名使用的是什么,都会默认转换为字符串类型
__proto__
该属性不能设置非对象的值
判断是否存在该属性
object.key===undefined
true不存在,false存在"key" in object
true存在,false不存在
for in
属性名是整数?升序排列:创建顺序排列;
克隆合并
Object.assign(dest,[src1,src2...])
- dest=>目标object
- [src…]=>源对象列表
- 用于克隆或合并对象
- 存在的属性会被覆盖
- **存在问题:**被克隆对象的子对象并未被克隆而是引用。
//使用深层克隆来解决子对象的引用问题
//方法1:
function deepClone(origin,target){
var target =target || {};
let toStr =Object.prototype.toString,
arrStr="[object Array]";
for (let prop in origin){
if (origin[prop]!=null && typeof(origin[prop]))=="object"{
target[prop] = (toStr.call(origin[prop])==arrStr)?[]:{};
deepClone(origin[prop],target[prop]);
}else{
target[prop]=origin[prop];
}
}
}
//方法2:
//方法无法被拷贝过去。
obj2 =JSON.parse(JSON.stringify(obj1));
11.2 方法
user = {
sayHi:function(){
alert("hello");
}
};
//简写
let user = {
sayHi(){
alert("hello");
}
};
this
- this的指向由上下文决定
- 没有对象调用的情况下 this==undefined
- 箭头函数内的this取决与外部。
链式调用
再方法中添加return this;
完成链式调用
11.3 构造函数
new.target
new.target
可以检测用户调用该函数时候是否使用了new
11.4 可选链"?."
- 问题:如
user.address.street
,有些用户对象填写了address则可以调用,有些没有填写,则会报错。 - 解决方案:
- 再过去使用
(user && user.address && user.address.street)
确保不会报错, - 现在
(user?.address?.street);
- 解决方案只能保证不报错,如为空返回undefined。
- 再过去使用
- 不要过度使用可选链接,只放在必要的地方 如
user.address?.street
- 可以用于删除,可以用于读取,不可以写入。
?.
检测左侧对象或属性- 新
12 垃圾回收
- 不可达皆回收
13 Symbol
symbol类似与一种标记,如其名。
14 对象的原始值转换
原始值就是基本数据类型的值
语法:
Symbol.toPrimitive(input,preferedType?);
步骤:
转Number=>
- 如果input是原始值,返回input;
- 如果input是对象,调用input.valueOf(),如果结果是原始值,则返回结果;
- 调用input.toString(),如果是原始值,返回结果;
- 抛出Error
转String=>
- 如果input是原始值,返回input;
- 如果input是对象,调用input.toString(),如果结果是原始值,则返回结果;
- 调用input.valueOf(),如果是原始值,返回结果;
- 抛出Error
默认情况下,日期会被认为转为字符串,其它转为Number;
[]+[]; //""
[]+{}; //[object object];
{}+[]; //0
如何判断是String还是Number呢?
->hint
只有三种hint
:
- String
- Number
- default 二元不确定的时候
使用例子
//例1: 使用系统Symbol
let user ={
name:"Wang",
money:1000,
[Symbol.toPrimitive](hint){
alert(`hint:${hint}`);
return hint == "string"? `{name:"${this.name}"}`:this.money;
}
};
console.log(user);//hint:string ->{name:"Wang"}
console.log(+user);//hint:number -> 1000
console.log(user + 500); //hint:default ->1500
//例2: 不使用Symbol
let user ={
name:"Wang",
money:1000,
toString(){
return `{name:"${this.name}"}`;
},
valueOf(){
return this.money;
},
};
两个例子区别在于:使用Symbol.toPrimitive(hint)
要求必须有返回值,使用toString()
和valueOf()
没有返回值会忽略