变量类型和计算
值类型
String Number Boolen Symbol (符号) Undefined 保存在栈中,占据固定空间
执行一个方法时,每个方法会创建自己的内存栈,执行结束后内存栈会自行销毁。
引用类型
Object Array null(null 是特殊的引用类型,指针指向空地址) 值保存在堆中,栈中保存内存地址(指针)。
函数(函数是一种特殊的引用类型,但是不能用作储存数据,所以没有拷贝克隆一说)
堆中的value不会随着方法执行结束而销毁,因为这个这个vlaue还被其他变量引用,只有当value不再被任何比变量引用时,才会被销毁。
typeof
typeof能识别所有的值类型 String Number Boolean Symbol undefined
typeof识别函数 function
typeof(console.log) //function
typeof识别引用类型(不会细分)把array null object都识别为object
typeof([]) //object
typeof(null) //object
字符串拼接
const a = 100 + 10; // 110
const b = 100 + `10`; // '10010' 遇到字符串全转为字符串
const c = true + `10`; // 'true10'
==
==是不严格相等,在比较过程 类型相同时比较大小 ,类型不同会先将比较数进行强制类型转化,在进行值比较
0 == ''// true
0 == false// true
1 == true //true
2 == true //false
null == 0 //false
null = false //false
false == ''// true
null == undefined // true
// 除了== null之外 其他都用===
const obj = {a: 100}
if(obj.a == null){} // 相当于if(obj.a===null||obj.a===undefined){}
类型转换
- 如果任一操作数是布尔型,会转换成数值,false转换为0;true转换为1
- 如果是数字和字符串,会尝试将字符串转为数字,再比较相等
- 如果一个操作数是对象,另一个不是,则调用对象的valueOf()方法取得原始值,再根据前面的规则比较
- 如果任一操作数是NaN,== 始终返回false !=始终返回true
- null == undefined //true
- null和undefined 不能转换成其他类型值进行比较
- 如果两个操作数都是对象,则比较他们是不是同一个对象。
if语句和逻辑运算
truly变量 !!a === true的变量
falsely变量 !!a === false的变量
// 以下是falsely变量 除此之外都是truly变量
!!false === false
!!'' === false
!!undefined === false
!!null === false
!!NaN === false
!!0=== false
// truly 变量
const a = true
if(a){}
const b = 100
if(b){}
// falsely变量
const c = ''
if(c){}
const d = null
if(d){}
let e
if(e){}
变量类型判断
typeof
typeof 判断一些复杂数据类型时会统一返回object
typeof 'a' //string
typeof 1 //number
typeof NaN //number
typeof null //object
typeof undefined //undefined
typeof {} //object
typeof [] //object
typeof function(){} //function
typeof class a{} //function
使用typeof 判断NaN会返回Number;
使用typeof判断null,数组和对象时都会判断为Object
typeof可以用来判断String undefined
instanceof
引用值也称作对象(object),在js中除了原始类型之外的值都是引用类型,有这么几种内置的引用类型:Object,Array,Date,Error,RegExp。使用typeof运算符都会返回’object’.
instanceof一般用来判断引用类型数据 ,比如
num instanceof Number, // false
str instanceof String, // false
bool instanceof Boolean, // false
arr instanceof Array, // true
new Date() instanceof Date, // true
reg instanceof RegExp, // true
arr instanceof Object, // true--注意
new Date() instanceof Object // true--注意
obj instanceof Object, // true--注意
从结果可以看出instanceof不能判断值类型,但是引用类型可以,值得注意的是内置的引用类型在instanceof Object的时候的值都是true,这就导致判断是对象时不准确
constructor
bool.constructor === Boolean;// true
num.constructor === Number;// true
str.constructor === String ;// true
arr.constructor === Array ;// true
obj.constructor === Object ;// true
fun.constructor === Function ;// true
Symbol.constructor === Symbol ;// true
undefined和null没有contructor属性
constructor不能判断undefined和null,并且使用它是不安全的,因为contructor的指向是可以改变的
Object.prototype.toString
在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。
function foo(){};
Object.prototype.toString.call(1); '[object Number]'
Object.prototype.toString.call(NaN); '[object Number]'
Object.prototype.toString.call('1'); '[object String]'
Object.prototype.toString.call(true); '[object Boolean]'
Object.prototype.toString.call(undefined); '[object Undefined]'
Object.prototype.toString.call(null); '[object Null]'
Object.prototype.toString.call(Symbol());'[object Symbol]'
Object.prototype.toString.call(foo); '[object Function]'
Object.prototype.toString.call([1,2,3]); '[object Array]'
Object.prototype.toString.call({});'[object Object]'
判断是否是数组
Array.isArray()
用于确定传递的值是否是一个Array。如果对象是Array,则返回true,否则为false。
Array.isArray([1, 2, 3]);
// true
Array.isArray({foo: 123});
// false
Array.isArray("foobar");
// false
Array.isArray(undefined);
type of和instance of原理
type of 返回数据类型, instance of 返回布尔值
type of能准确判断基本数据类型(null除外),但是判断引用数据类型会出错
instance of能判断引用数据类型,但不能判断基本数据类型
type of :js储存变量的时候会在机器码低位储存类型信息。 对象机器码类型信息是000;null 机器码类型信息是0,typeof null会被视作对象。
instanceof 主要的实现原理就是只要右边变量的 prototype 在左边变量的原型链上即可
class类
class基本语法
JavaScript中创建实例对象的传统方法是通过构造函数,例如:
function Point(x,y){
this.x = x
this.y = y
}
Point.prototype.toStr = function(){
return `${this.x}------${this.y}`
}
var pt = new Point(1,2)
在ES6中引入来Class类的概念,作为对象的模版。通过class关键字可以定义类。
class可以看作只是一个语法糖,它的功能ES5也能做到,新的class写法让对象原型更加清晰,也更面对对象编程。
将上面代码通过class写法就是:
class Point1{
constructor(x,y){
this.x = x
this.y = y
}
toStr(){
return `${this.x}------${this.y}`
}
}
var pt1 = new Point1(1,3)z
上面代码定义的类,里面的constructor方法,实际上就是构造方法 验证如下
class Point1{
constructor(x,y){
this.x = x
this.y = y
}
toStr(){
return `${this.x}------${this.y}`
}
}
Point1.prototype.constructor===Point1 // true
this关键字则代表实例对象
Point1类除了构造方法,还有一个toStr方法,定义该方法时前面不需要加function关键字,与构造方法之间也不需要逗号分隔。
es6的类,完全可以看作是构造函数另一种写法。
class Point {
// ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
构造函数的prototype属性,在class类上仍然存在,类的方法实际上都是定义在prototype上的
class Point{
toStr(){
//....
}
add(){
//....
}
fixs(){
//....
}
// ....
}
//等同于
Point.prototype={
toStr(){
//....
},
add(){
//....
},
fixs(){
//....
}
}
因此,调用类上的方法,实际就是调用其原型上的方法
class B{}
let b = new B()
b.constructor === B //true
b.constructor === B.prototype.constructor//true
上述代码中,b是B类的实例,b的constructor方法就是B类原型上的constructor方法。
constructor方法
constructor方法是类的默认方法,在通过new创建一个实例时,会自动调用该方法。
一个类必须有constructor方法,如果该方法没有被显式创建,则默认添加一个空的constructor方法
class Point{}
//等同于
class Point{
constructor(){}
}
上述代码中创建了一个空的类,JS会自动给其添加一个空的constructor方法,constructor方法默认返回实例对象(即this),完全可以指定成另外一个对象。
class Foo{
constructor(){
return Object.creat(null)
}
}
new Foo()instanceof Foo //false
如以上代码所示,在constructor中返回一个全新的对象,导致实例对象不是Foo的实例
与es5一样,实例的属性除非显式定义在this上,否则就是定义在原型上
class Point{
constructor(x,y){
this.x = x
this.y = y
}
toStr(){
return `${this.x}----${this.y}`
}
}
//hasOwnProperty:hasOwnProperty() 方法用来检测一个属性是否是对象的自有属性,而不是从原型链继承的
let point = new Point(12,3)
point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toStr') // false
point.__proto__ === Point.prototype //true
point.__proto__.hasOwnProperty('toStr') // true
上面代码中x和y都是定义在this上属于point实例对象的自身属性,而toStr方法则是定义在Point类的原型上
与es5一样,所有的原型都共享一个原型对象 proto
let point1 = new Point()
let point2 = new Point()
point1.__proto__ === point2.__proto__ //true
这也意味着,可以通过实例的proto属性为“类”添加方法。
对象遍历
for… in
Object.keys()
Object.values()
Object.entries()
返回给定对象自身可枚举属性的键值对数组(不枚举原型链上的属性)
natureColors:{
colorC:'green',
colorD:'yellow'
}
Object.entries(natureColors);
// => [ ['colorC', 'green'], ['colorD', 'yellow'] ]
Set 和 Map
Set
允许存任何类型的值,但是成员都是唯一的,不可重复。
Set 本身是一个构造函数,可以接收数组或者其他具有iterable接口的数据结构。
特殊值
Set加入值的时候,不会进行类型转换,所以5和‘5’是不重复的,判断依据类似与’===’,但是也有一些特殊值
- NaN === NaN //false 但是在Set中,看作重复值,只能出现一次
- 空对象可以出现多次。
方法
- has(value):返回布尔值,是否有某元素
- add(value):添加某个值
- delete(value):删除某个值
- clear():清空
遍历方法
- keys():返回键名的遍历器。
- values():返回键值的遍历器。
- entries():返回键值对的遍历器。
- forEach():使用回调函数遍历每个成员。
可以使用for of遍历 keys(),values(),entires()
Map
保存键值对,任何值都可以为键或者值
Map和Object 区别
- Map中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。
- Map的键值对个数可以从 size 属性获取,而 Object 的键值对个数只能手动计算。
- Object 都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。
Map方法
- set(key, val): 向Map中添加新元素
- get(key): 通过键值查找特定的数值并返回
- has(key): 判断Map对象中是否有Key所对应的值,有返回true,否则返回false
- delete(key): 通过键值从Map中移除对应的数据
- clear(): 将这个Map中的所有元素删除
遍历方法
- keys():返回键名的遍历器
- values():返回键值的遍历器
- entries():返回键值对的遍历器
- forEach():使用回调函数遍历每个成员
可以使用for of遍历 keys(),values(),entires()