js的值类型和引用类型
值类型:数值、布尔、null、undefined
引用类型:对象、数组、函数
js的值类型和引用类型
值类型:数值、布尔、null、undefined
引用类型:对象、数组、函数
类型判断
typeof
返回字符串instanceof
后接类型,返回bool
隐式转换
- (1+2)+”3” //“33”
当多个运算符被重载时,js会盲目的选择valueOf; 所以要么明确重载一个,要么保证重载的俩个值相同。
12345678910var obj = {toString: function() {return "hh";},valueOf: function() {return 12;}};//或者 obj.prototype.toString = function () ..."object:" + obj;//"object:17"真值运算;if、|| 、&&需要布尔的运算
js有7个假值:false、0、-0、””、NaN、null、undefined;
== 的强制转换
Param1 | Param2 | Force Format |
---|---|---|
null | undefined | 不转换,总返回true |
null or undefined | 非null、非undefined | 不转换,总返回false |
原始类型 | Date对象、非Date对象 | 原始类型转换为数字,Date对象(优先toString)、非Date对象(优先valueOf)转换为原始类型 |
原始类型 | 原始类型 | 将原始类型转换为数字 |
Unicode字符
- js字符串由16位代码单元组成,而不是由unicode代码点组成。
- js使用俩个代码单元表示16位以上的unicode代码点,称为代码对。
- 代码对甩开了字符串元素计数,length、charAt、charCodeAt方法以及正则表达式模式。
字符串Trick
它字符串的构造
12
let tt= 'as';let at = `aa${tt}`//注意这不是单引号
闭包
|
|
立即调用函数表达式
变量声明提升
js对变量的作用域是函数级的,不是块级的。
命名函数
|
|
所以建议少用命名函数,多用匿名函数。
eval函数
- 书上的建议是不要用它创建变量,同名变量会导致访问相同地址的变量
- 间接调用eval函数;
(0,eval)(src)
0值无意义以达到强制使用间接调用的目的。src是传入给eval的参数。
call和apply
obj.temprorary = f;
var result = obj.temprorary(arg1, arg2);
delete obj.temprorary;
当想使用其他对象的某个属性时,这种方法不仅别扭,而且相当危险。
所以有了call和apply
apply只是让数组变成多个参数。
js函数有个arguments的默认参数,也是数组。所以默认支持变长参数函数。
bind
|
|
使构造函数与new无关
|
|
将状态存储到示例对象而不是原型对象
|
|
this隐式绑定问题
|
|
在子类的构造函数中调用父类的构造函数
继承可以用Object.Create
注意不要让子类属性和父类属性重名,这样会导致冲突访问同一属性。
避免继承标准类
猴子补丁
由于平台的不同有些对属性的修改可能会导致覆盖,应该如此
使用object实例直接构造轻量级字典
书上建议使用实例来增加属性,而不是原型的prototype.
这样保证for in的正确执行
不建议用for in来循环数组,(特别是数字类型的数组;即使用[],但是遍历的变量是字符型)
使用null原型防止原型污染
|
|
使用hasOwnProperty避免原型污染
即使是个空的对象,也继承了大量属性。
为了避免空对象的判断,可以使用hasOwnProperty
使用数组而不要用字典来存储有序集合
|
|
书上说,for…in 在此类数组中它由环境的不同可能会选择不同的顺序来枚举对象。
所以即使以上写法可以,也建议使用普通的循环。
js的属性
属性点访问和方括号访问
属性允许字符和变量
点访问只能访问字符属性
方括号访问访问字符时obj[‘pro’],访问变量时obj[ele]一般属性的字符定义(括号定义必须是字符):obj.pro = …; obj[‘pro’]=…
变量定义 obj[ele]= …
枚举性
对于对象来说,属性有可枚举和不可枚举
默认从prototype
来的是可枚举的
不可枚举一般用
当属性可枚举时:for…in能遍历出来。Object.keys()能遍历出来(数组非数字属性也能遍历出来)
当属性不可枚举: 只有Object.getOwnPropertyNames()能遍历出来, 和 …in语句
创建位置
属性明确创建:
构造函数this.a=...
创建的对象obj定义属性obj.a=...
原型创建:
创建的对象obj定义属性obj.prototype.a=...
class体内定义的属性
由于依附在原型上,hasOwnProperty
,for...in
, getOwnPropertyNames
都会无法返回对应属性,只有...in
语句能返回
不要在prototype中增加可枚举的属性
|
|
书上解决方法是封装成函数,如果实在要封装成属性,要如下写。
|
|
我感觉这样写又会污染原型,还是写成函数好点。
避免枚举期间修改对象
直接引用书上:
- 当使用for…in循环枚举一个对象的属性时,确保不要修改对象。
- 当迭代一个对象是,如果该对象可能会在循环期间被改变,应该使用while或for来代替for…in
迭代方法优于循环
书上建议多用 forEach/map/every 这些本身的迭代方法来代替循环。
函数默认值
es5上没有默认值得设定
编写方法支持方法链
|
|
不要阻塞I/O事件队列
如下代码会一直等待下载文件完成才继续执行下去,会导致卡死情况。
如下代码就不会阻塞了。
对异步循环使用递归
|
|
循环的代码会等待下载执行完成。用递归函数在时间循环的单独轮次中执行迭代。
js递归函数同步调用太多次会导致失败(承受力各不同,几百次以上)
私有公有静态属性的访问
|
|
调用公有方法、公有属性,必须先实例化对象。公有方法不能调用私有方法和静态方法。
(即:ws.sname 不可以 user.sanme可以; )静态方法和静态属性无需示例化可访问 (user.name可以)
- 私有方法和属性外部无法访问 (user.getHName() 不可以 user().getHName() 不可以)
变量提升
|
|
- js解释器会把声明提升到作用域(函数作用域)的最前面(即使写代码时放在最后也会被提升)
new的优先级
用上面现成的代码做例子:
|
|
import的括号
未加括号是默认引用:import A from './A'
import Mya from './A'
;这样引用的都是A
文件里的export default
加了括号是指定引用:
import {Som} from './A'
,A
文件里必须有个export Som ...
导出
import A, { Mya, Som} from './A'