JavaScript数据类型(一)

一、数据类型

原始类型**

number、boolean、null、underfined、string、symbol
(存放于栈中,占内存小,读取快),也就是说他们的值是直接存储在变量访问的位置,值是不可变的,改变只是“指针指向的改变”,比较是值得比较

1.null、underfined
①null

▪ nulll代表空值。typeOf null为Object是js的一个bug.
▪ null类型被看做空对象指针,只有一个值,即null值,所以在用typeof操作符去检测null类型的值得时候,结果是object类型;
▪ 如果你定义了一个变量,但是想在以后把这个对象当做一个对象来使用,最好将该对象初始化为null值

②underfined

▪ underfined代表未定义。underfined和not defined区别,前者代表定义了但没有赋值,后者表示没有定义。相同点,typeOf都返回underfined.
▪ 调用函数时,应该提供的参数没有提供,该参数等于undefined;
▪ 对象没有赋值的属性,该属性的值为undefined;
▪ 函数没有返回值,默认返回undefined。

2.字面量、String()、new String()

▪ 字面量就是没有用标识符封装起来的量,是“值”的原始状态; 如const int A = 1; // A 是常量,1 是字面量
▪ String和字面量的方式都可以返回基本类型
▪ new String()返回 object

 'aa' instanceof String  //false
 new String(a) instanceof String  //true
 let a=123;
 String(a)   //"123"
  console.log(String(null))  // 输出:null
  console.log(String(underfined))  // 输出:underfined
 new String(a)  //String {"123"}
 new String(a)=='123'      //true
 new String(a)==='123'   //false

Q1、为什么基本类型’kk’ 可以调用length或者toString()方法和属性呢?

在这里,JavaScript会将字符串的值调用new String()方法转成对象,这个对象继承了字符串的方法,并用来处理属性。一旦属性引用结束,这个临时包装对象就会销毁。
包装对象,即存取字符串,数字或布尔值的属性时临时创建的对象
null和underfined没有包装对象

   
/*
    基本包装对象 1、String 2、number 3、Boobear
*/
var str = 'dwkdwqudu2i';
var str2 = str.charAt(0);
cconsole.log(str2);/* 在后台的执行过程 */
var str = new String('dwkdwqudu2i');
var str2 = str.charAt(0);
str = null;//把原来的str清空为null
console.log(str2);/* 
    设置原型就可以不会销毁 ,但是会污染所有的String  
*/
String.porototype.name = 12;
console.log(str.name);//12

Q2、为什么2.toString()会报错?
前面的. 既可以理解为小数点,也可以理解为方法的调用。在这里,2.toString()在解释器看来其实是(2.)toString(),解决方法如下:

  2..toString();
  (2).toString()  //加个括号
  2 .toString()   //加个空格
  2.0.toString()

3.基本数据类型不可以添加属性和方法

  let user = 'zhangsan'
  user.age = 18
  user.method = function () {
    console.log('12345')
  }
  console.log(user.age) // 输出:undefined
  console.log(user.method) // 输出:undefined
引用类型**
object (在JS中除了基本数据类型以外的都是对象)
 (**可以动态分配内存,可以存大数据**),是保存在堆(heap)中的对象,
 也就是说,存储在变量处的值是一个指针,该指针地址->指向存储对象的内存处;值是可变的,比较是引用的比较
  //obj1赋值给obj2,实际上这个堆内存对象在栈内存的引用地址复制了一份给了obj2,
  //但是实际上共同指向了同一个堆内存对象,所以修改obj2其实就是修改那个对象,所以通过obj1访问也能访问的到
   let obj1 = new Object();
   let obj2 = obj1;
   obj2.name = "我有名字了";
   console.log(obj1.name);   // 我有名字了

二、深浅拷贝

1.浅拷贝
一层拷贝,只会拷贝所有的属性值到新的对象中,如果还是对象则拷贝地址
在这里插入图片描述
▪ Object.assign();
▪ Array.slice();
▪ Array.concat();
▪ […array]
2.深拷贝

▪ 序列化
JSON.stringify - >将对象序列化为字符串
JSON.parse - >从字符串反序列化对象

JSON.parse(JSON.stringify(a))
缺点:对函数、underfined和symbol序列化后会丢失

▪ 递归遍历
90%的情况都可以用浅拷贝和序列化实现,如果有特殊情况需要递归遍历。
在这里插入图片描述
▪ MessageChannel 消息通道
MessageChannel API允许我们创建一个新的消息通道,并通过他的两个 MessagePort 属性发送数据。
和webworker类似。数据是深拷贝,不会丢失 underfined,循环引用也可以。但是对函数和symbol还是不行

三、类型判断

1.typeof 操作符
主要用于判断数据是不是基本数据类型,但是无法判断出具体引用类型

▪ “undefined” ——如果这个值未定义;
▪ “boolean” ——如果这个值是布尔值;
▪ “string” ——如果这个值是字符串;
▪ “number” ——如果这个值是数值;
▪ “object” ——如果这个值是对象或 null ;
▪ “function” ——如果这个值是函数。
2.instanceof 操作符
用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上
这里主要的目的是用来检测引用类型
种变量判断可以检测出9种(Number、String、Boolean、Symbol(ES6)、Object 、Array 、Date 、RegExp 、Function 类型),undefined和null 不被检测为object,因为js中没有这种全局类型

//==对于number,string,boolean这三种类型,只有通过构造函数定义==,这样定义才能检测出,比如:
let num =new Number(1);
let str = new String('abc');
let bool = new Boolean(true);·
//下面这样定义是检测不出来的
let num = 1;
let str = 'abc';
let bool = true;

3.Object.prototype.toString.call()
对象的一个原生原型扩展函数,用来精确的区分数据类型

   Object.prototype.toString.call(null)  //"[object Null]"
   Object.prototype.toString.call(new Map())  //"[object Map]"
   Object.prototype.toString.call(function* (){})  //"[object GeneratorFunction]"
   Object.prototype.toString.call(Promise.resolve())  //"[object Promise]"
   let arr2=[1,'2',[1,2],null,{'a':1}];
   Array.prototype.toString.call(arr2)    //1,2,1,2,,[object Object]"
   Function.prototype.toString.call(function(){})  //"function (){}"
   Function.prototype.toString.call({})   //Uncaught TypeError: Function.prototype.toString requires that 'this' be a Function

总结:除了Object和Array两种情况,其他类型都不支持非自身实例,通过this绑定调用该Object子类原型对象上的toString()方法,说明重写toString()方法时,限定了调用方法对象的类型,非自身对象实例不可调用

4.toString、valueOf

①基本类型的valueOf会返回自身的原始类型,而Array、Object和Function都会返回自身,Date返回时间戳
②null和underfined没有相应的构造函数,所以无法调用toString()方法。只是基本数据类型,不能访问任何属性和方法。

  let obj={a:1,b:[1,2]};
  let fun=function(){};
  let arr=[1,'2',null,'underfined'];
  obj.valueOf();        //{a: 1, b: Array(2)}
  obj.toString();       //"[object Object]"
  arr.valueOf();        //[1, "2", null, "underfined"]
  arr.toString();       //"1,2,,underfined"
  fun.valueOf();        //function(){}
  fun.toString();       //"native code"
  new Date().toString() //"Tue Nov 12 2019 17:18:50 GMT+0800 (中国标准时间)"
  new Date().valueOf()   //1573550374068
  window.toString()   //"[object Window]"
  let errors=new Error('kkk');
  errors.valueOf()    //Error: kkk
  errors.toString()   "Error: kkk"
  //注:{}.toString() 不加()会被当成代码块,报错
  {a:1}.toString()     //报错 Uncaught SyntaxError: Unexpected token .
  ({a:1}).toString()   //"[object Object]"  
发布了15 篇原创文章 · 获赞 2 · 访问量 411

猜你喜欢

转载自blog.csdn.net/goUp_self/article/details/103010761