数据类型
什么是引用类型,值类型
- 值类型key与value的值存储再栈中(量小)
- 医用类型再栈存储引用地址,在堆中存储数据(量大)
- 把引用类型赋值给一个变量,是把变量的引用地址指向引用类型堆中地址
有哪些值类型
- String:字符串
- Number:数字
- Boolean:布尔值
- undefined:未定义
- null:空(特殊)
- Symbol:符号
有哪些引用类型
- Object:对象
- Array:数组
- Function:函数
- Map:地图
- Set:集合
如何判断数据类型
typeof:类型
左边检测-----------右边返回结果
- typeof “abc” ----------- string
- typeof 123 ----------- number
- typeof true ----------- boolean
- typeof undefined ----------- undefined
- typeof null ----------- object(null空指针)
- typeof {} ----------- object
- typeof [] ----------- object
- typeof function() ----------- function
- 适合判断值类型与引用类型,不能判断具体引用类型
instanceof:实例
- [] instanceof Array ----------- true
- [] instanceof Object ----------- true
- {} instanceof Array ----------- false
- {} instanceof Object ----------- true
- 判断是否是其原型链上的实例,只要构造函数在原型链上都返回true
- []由Array创建的,Array是Object的子类,instanceof Array和Object都返回true
constructor:构造函数
- 判断实例对象构造函数
- [].constructor == Array true
Array.isArray():是否为数组(数组专用)
Object.prototype.toString.call(obj):原型(最精确的方法)
- 方法Object.prototype.toString.call(obj).slice(8,-1);
- 返回数据的精确类型
function getType(obj){
return Object.prototype.toString.call(obj).slice(8,-1);
}
浅拷贝与深拷贝
浅拷贝
三种方法:
- 扩展{…obj}
- for遍历
- Object.assign()
// js拷贝对象
// 浅拷贝,只能拷贝值类型,引用类型数据还是指向地址
var obj1 = {
name:"mumu",
age:18,
friend:["小红","小蓝",{
name:"小绿",
job:"teacher"
}]
}
// ES6扩展
var obj2 = {...obj1}
// 循环
var obj3 = {}
for(var k in obj1){
obj3[k] = obj1[k];
}
// Object.assign把参数的两个对象进行合并,属性相同后面覆盖前面
var obj4 = Object.assign(obj1,{});
深拷贝
- JSON.parse(JSON.stringify(数据)):json数据类型只支持不二,字符串,数字,null,undefined,array,object
会忽略函数等其它类型数据 - 通过判断类型 递归深拷贝(递归就是函数自己调用自己,一定要有结束条件)
// js拷贝对象
// 深拷贝,目标对象与元对象相互之间切断联系
var obj1 = {
name:"mumu",
age:18,
friend:["小红","小蓝",{
name:"小绿",
job:"teacher",
say(){
alert("你好,我是"+this.name)
}
}]
}
// JSON转字符串,字符串转对象
var obj2 = JSON.parse(JSON.stringify(obj1))
// json字符串的值指挥保留数组、对象、字符串、数字、null、undefined
// 对象中的函数会被过滤掉(一般数据也是不带函数的)
- 通过递归进行深拷贝
var obj1 = {
name:"mumu",
age:18,
friend:["小红","小蓝",{
name:"小绿",
job:"teacher",
say(){
alert("你好,我是"+this.name)
}
}]
}
function deepCopy(obj){
if(typeof obj == "object" && obj!= null){
var temp = null;
if(obj instanceof Array){
temp = [];
for(var i=0;i<obj.length;i++){
temp[i] = deepCopy(obj[i])
}
}else{
temp = {};
for(var k in obj){
temp[k] = deepCopy(obj[k]);
}
}
return temp;
}else{
return obj;
}
}
var obj2 = deepCopy(obj1);
隐式转换
看符号
-
字符串连接符号 会尝试把其它类型转换为字符串
-
加减 * / == 会尝试把其它类型转换为数字
注意:1、转换失败 NaN
2、false转换为0
3、true转换为1 -
< > <= >= == === || && ! 比较与逻辑会尝试把其它类型转换为布尔值
-
falsely变量会转换为false(false “” 0 NaN undefined null)
// 数据类型转换:强制转换,隐式转换
// 强制转换Number()转换为数字 String()转换为字符串 Boolean()转换为布尔值
// 隐式符号转换
// + 字符串连接符号(隐式转换为字符串)
// + - * / 数学云散(隐式转换为数字)
// < > <= >= == === || && ! 比较与逻辑(隐式转换为布尔值)
var a = "100"
var b = 10;
var c = a + b;// 10010
// alert(c)
// 01 字符串和任意数据+连接都会转换为字符串
var a = "10";
var a = "abc10";
var a = true;
var a = false;
var b = 2;
var c = a*b; //20
// 02暑促额运算符号会尝试隐式装欢数据为数字
// 如果数据没有转换数字成功 结果就是NaN(not a number的检测)
// alert(c)
var a = "";
var b = true;
alert(!!a);//false
// 03逻辑与比较运算符会把变量转换为布尔值
// 空字符串 0 null undefined NaN才会被转换为false,其它都会被转换为true
// 把以上得到变量值称为falsely变量值,其它的变量都称为truely变量值
alert(!!-1);//true
等于等于() 和严格等于(=)
等于等于(==)
- 判断隐式转换后的值
- “100” == 10 ---------- true
- null == undefined ---------- true
- 0 == false---------- true
- 特例:NaN === null ---------- false
- {} == {} ---------- false
- [] == []---------- false (指向不同的内存地址)
// ==判断隐式转换后值是否相等
// ===判断雷丁与值是否相对
// ==
alert(100 == "100");//true 如果两遍类似数字会优先转换为数字
alert("" == false);//true
alert(1 == true);//true
alert(null == undefined);//true 隐式转换后都为false
alert(null == null);//true 空指针都指向一个地方(空)
alert(undefined == undefined);//true
alert(null == NaN);//false (特殊)数字不等于空
alert([] == []);//false 两块不同的内存地址
alert({} == {});//false 两块不同的内存地址
严格等于(===)
- 判断类型和值是否对相对
- 应该任何时候都是用===
- 当判断是否为null或者undefined可以为特例
- null === null ----------true
// ===严格等于 判断类型与值是否相等
alert(0 === "") //false
alert([] === []) //false
alert({} === {}) // false
alert(null === undefined) //fasle
alert(null === null) //true
if判断
- if()中判断的是否为truely变量
- falsely变量:false “” 0 NaN undefined null 两次取反(!!a 得到结果为false的变量)
- 除了这几个falsely变量之外其它都是truely变量
var a = 10;
if(a){
alert("条件通过")//对
}
var b = "";
if(b){
alert("条件通过")
}else{
alert("条件不通过")//对
}
// 01 if的判断只要求括号里的表达式结果是否为truely变量
// 02 falsely变量 对变量取两次反 !! 的都结果为false的变量 称为falsely变量
// 03 false “” 0 NaN undefined null
// 04 除了这几个falsely变量之外其它都是truely变量
逻辑且和逻辑或
-
A||B A为真(truely)结果为A,否则结果为B
-
A&B A为假(falsely)结果为A,否则结果为B
-
判断对象
- if(a&&a.b&&a.b.c){}
- if(a?.b?,c){}
- 如果有a并且有a.b并且有a.b.c
- if(a.b.c){}不推荐
-
逻辑或:
// || 或 如果前面的变量为truely 最终的结果为第一个,如果为faslely 结果为第二个
var a = 15||0;//15 转换结果为true a的值就是15
var b = false || 50; // false转换的结果为fasle b的值就是50
var c = false || undefined;
var d = 0 || false;
var re = localStorage.getItem("num") || 5;//num的值娶不到,或者为0,或者为null 最终结果为5
- 逻辑且:
// && 前面是truely变量返回后面的值,前面是falsely变量直接使用前面的值
var c = 15&&20;//20
var c = false&&18;//false
alert(c)
// 在逻辑判断中&&前面的值为falsely,后面的不执行,前面为truely,则看&&后面的值
var obj = {
age:12,
leg:{
width:100,
henght:34
}
};
// if(obj.abc.height){
// if(obj&&obj.abc&&obj.abc.height){
if(obj?.abc?.henght){//ES6语法
alert("通过")
}else{
alert("不通过")
}
// Uncaught TypeError:Cannot read properties of undefined (reading 'height')
// 在undefined上面读取height读取不到
原型与原型链
名词
类
- (创建对象实例的模板)本质上都是函数
- 构造函数用new来执行的函数
- class xxx{}
实例
- 由类创建的对象 ,本质上就是个对象
什么是原型与原型链
原型
- 显示原型:类/构造函数都是一个显式原型ptotype,本质上就是个对象
- 隐式原型:每个实例都有一个隐式原型__proto__
- 显与隐的关系:类显示原型protype等于其创建的实例的隐式原型__proro__
原型链
- 查找对象实例的方法和属性时,先在自身找,找不到则沿着__proro__向上查找,__proro__形成的链条关系我们称之为原型链
原型与原型链的作用
实现了js的继承
class的extends方法
- class Student extends
People{constructor(name,age,no){//类中继承构造函数super(name,age)}}
class Student extends{
People{constructor(name,age,no){//类中继承构造函数
super(name,age)
}
}
使用原型链
1、student构造函数中继承People
- function Student(name,age,no){People.call(this,name.age);this.no =
no;}
2、继承原型链 - Student.prototype = Object.create(People.prototype);
3、修正Student构造函数 - Student.prototype.constructor = Student;
//创建people类
function People(name,age){
this.name = name;
this.age = age;
}
//给people显式原型添加eat方法
People.prototype.eat = function(){
console.log(this.name + "正在吃饭");
}
// 创建学生类继承People类
function Student(name,age,no){
People.call(this,name.age);
this.no = no;
}
//让Student原型链继承People的原型链
Student.prototype = Object.create(People.prototype);
//修正Student显式原型链上的构造函数
Student.prototype.constructor = Student;
//在Student显式原型链添加方法
Student.prototype.study = function(){
console.log(this.name + "证字啊好好学习,天天向上");
}
//构建Student的实例s1
var s1 = new Student("小王",18,9527);
实现了实例的公用属性和方法
所有的数组将拥有max方法
- Array.prototype.max = function(){return Math.max(…this)}
Array.prototype.max = function(){
return Math.max(...this)//返回数组最大值
}
所有的字符串将拥有reverse方法
- String.prototype.reverse = function(){return this.split(“”).reverse().join(“”);}
String.prototype.reverse = function(){
return this.split("").reverse().join("");
}
注意
- 一般不要修改js默认对象原型上的方法,扩展也要谨慎
- 进行不要再js默认对象的原型上添加方法
- vue2 数组的双向绑定劫持就是重写了数组原型上的方法实现的