数据类型
什么是引用类型,值类型
- 值类型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);//truealert(1 == true);//truealert(null == undefined);//true 隐式转换后都为falsealert(null == null);//true 空指针都指向一个地方(空)alert(undefined == undefined);//truealert(null == NaN);//false (特殊)数字不等于空alert([] == []);//false 两块不同的内存地址alert({} == {});//false 两块不同的内存地址
严格等于(===)
- 判断类型和值是否对相对
- 应该任何时候都是用===
- 当判断是否为null或者undefined可以为特例
- null === null ----------true
// ===严格等于 判断类型与值是否相等alert(0 === "") //falsealert([] === []) //falsealert({} === {}) // falsealert(null === undefined) //faslealert(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的值就是15var b = false || 50; // false转换的结果为fasle b的值就是50var c = false || undefined;var d = 0 || false;var re = localStorage.getItem("num") || 5;//num的值娶不到,或者为0,或者为null 最终结果为5
- 逻辑且:
// && 前面是truely变量返回后面的值,前面是falsely变量直接使用前面的值var c = 15&&20;//20var c = false&&18;//falsealert(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的实例s1var 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 数组的双向绑定劫持就是重写了数组原型上的方法实现的