js的数据类型到底是怎么划分的?

    技术2022-07-11  73

    这是一个令我困扰了很久的问题,基本数据类型是哪几种,引用类型到底包括哪些? 我把原来的笔记汇总了一下。 首先,我们要说明的就是js的数据类型有哪些。

    根据ECMA的表述,js的数据类型可以分为7类:

    number、string、boolean(相信这三类大家都了解,他们也被成为原始类型)

    undefined表示未定义、null表示空。

    symbol 为es6新增数据类型。

    Object对象,其中js内置了Function、Array、Date等对象。这些对象继承自Object对象,这个又可以展开讲一下原型链。但这里我们只说类型。看下去吧。

    文章目录

    数据类型null和undefined区别布尔值转化数值浮点数parseIntparseFloatisNaNisFinite 字符串对象查看属性方法删除属性是否存在属性 函数属性和方法作用域参数传递 闭包立即表达式 数组方法: 正则表达式String对象 类型判断typeofinstanceofconstructorObject.prototype.toString()

    数据类型

    null和undefined区别

    null是一个表示“空”的对象,转为数值时为0;undefined是一个表示"此处无定义"的原始值,转为数值时为NaN。

    布尔值转化

    一下六个值会被转为false,其余均被转为true。

    undefinednullfalse0NaN""或''(空字符串)

    其中空数组和空对象对应布尔值为true。

    数值

    浮点数

    javascript内部没有整数,转为浮点数进行。因此在两个浮点数比较的时候,往往会出现差错。

    经典面试题:

    0.1+0.2==0.3 //false

    解决方法1: 通过精度判断

    var delta = 1e-5; // 定义精度精确到0.00001 var a = 0.1+0.4; var b = 0.2+0.3; // 判断相差小于精度就认为相等 var isEqual = function (a,b,delta) { let sum = a + b; if(a + b - sum < delta) { console.log('a + b == sum'); }}; isEqual(a, b, delta)

    解决方法2: toFixed()方法

    自带的toFixed方法有问题,重写。

    Number.prototype.toFixed=function (d) { var s=this+""; if(!d)d=0; if(s.indexOf(".")==-1)s+="."; s+=new Array(d+1).join("0"); if(new RegExp("^(-|\\+)?(\\d+(\\.\\d{0,"+(d+1)+"})?)\\d*$").test(s)){ var s="0"+RegExp.$2,pm=RegExp.$1,a=RegExp.$3.length,b=true; if(a==d+2){ a=s.match(/\d/g); if(parseInt(a[a.length-1])>4){ for(var i=a.length-2;i>=0;i--){ a[i]=parseInt(a[i])+1; if(a[i]==10){ a[i]=0; b=i!=1; }else break; } } s=a.join("").replace(new RegExp("(\\d+)(\\d{"+d+"})\\d$"),"$1.$2"); }if(b)s=s.substr(1); return (pm+s).replace(/\.$/,""); }return this+""; };

    parseInt

    当小数点后位数超过5,则自动转化为科学计数

    parseInt对字符串转化为整数,如果输入是浮点数,先转成字符串。

    Int过程中挨个遍历字符,遇到第一个非数字的字符就返回。

    parseInt('123&') 123 parseInt(123+.3) 123 parseInt(123++=.3) VM1796:1 Uncaught SyntaxError: Invalid left-hand side expression in postfix operation 如果第一个字符为非数字,分两种情况:

    字符为+,若后面跟着数字,则返回数字,如果后面没有数字,则返回NAN

    parseInt(+123) 123 parseInt('+') NaN

    字符为其他,返回NaN

    parseInt('&123') NaN 如果第一个字符为0:

    第二个字符为x或X,则按16进制解析

    第二个字符为数字,按10进制解析。

    parseInt(023) 19 parseInt(0x23) 35

    当小数点后0的连续位数为5,则自动转化为科学计数,自动计数转化为字符串

    parseInt(0.000008) 8 parseInt(0.1234568) 0 parseInt(0.000008) 0

    parseFloat

    将字符串转化为float

    可以将科学计数法进行转换

    如果第一个字符不能转化为浮点数,则返回NaN。

    isNaN

    判断一个值是否为NaN. 数值会返回false。

    非数值会先Number,再使用isNaN。即

    isNaN('Hello') // true // 相当于 isNaN(Number('Hello')) // true

    字符串、对象、数组都返回true。

    判断isNaN的方法

    唯有NaN不等于自身。

    function myIsNaN(value) { return value !== value; }

    isFinite

    返回一个布尔值

    除了Infinity、-Infinity、NaN和undefined这几个值会返回false,isFinite对于其他的数值都会返回true。

    字符串

    可以通过数组索引的形式访问,但是并不能通过索引改变值。

    var s = 'hello'; delete s[0]; s // "hello" s[1] = 'a'; s // "hello" s[5] = '!'; s // "hello"

    length也不可改变

    对象

    js中的对象是浅拷贝,指向同一个内存地址。(其中数组、函数都是特殊的对象)

    原始类型都是值的拷贝。深拷贝

    查看属性方法

    var obj = { key1: 1, key2: 2 }; Object.keys(obj); // ['key1', 'key2']

    删除属性

    delete

    只能删除本身的属性,不能删除继承的属性。

    是否存在属性

    in 判断是否存在属性,但不能判断是否为继承属性

    hasOwnProperty判断是否为自身属性

    var obj = {}; if ('toString' in obj) { console.log(obj.hasOwnProperty('toString')) // false }

    函数

    一等公民

    属性和方法

    name属性返回函数的名字

    length属性返回函数定义时的参数个数

    toString()返回原生代码

    作用域

    全局作用域

    函数作用域

    块级作用域

    总之,函数执行时所在的作用域,是定义时的作用域,而不是调用时所在的作用域。

    正是因为这种特性,形成了闭包。

    var a = 1; var x = function () { console.log(a); }; function f() { var a = 2; x(); } f() // 1

    上面的代码中,x函数的作用域在全局,是定义时的作用域。

    参数传递

    如果是基本数据类型,是传值。

    如果是复合类型,则是传地址。

    在函数内部更改属性值,会改变。

    函数内部可以使用arguments获取传递的所有参数。虽然可以通过数组形式传递参数,但是并不具有数组的方法。

    两种转化为数组的方法:

    var args = Array.prototype.slice.call(arguments); // 或者 var args = []; for (var i = 0; i < arguments.length; i++) { args.push(arguments[i]); }

    闭包

    读取函数内部的变量让变量始终保持在内存中可以封装对象的私有方法和属性外层函数每次运行,都会生成一个新的闭包,而这个闭包又会保留外层函数的内部变量,所以内存消耗很大。因此不能滥用闭包,否则会造成网页的性能问题。

    立即表达式

    https://wangdoc.com/javascript/types/function.html 5.2部分详细讲解

    以function开头是语句,

    function(){ /* code */ }(); // SyntaxError: Unexpected token (

    所以这样写是不行的。

    为了避免解析上的歧义,JavaScript 引擎规定,如果function关键字出现在行首,一律解释成语句。因此,JavaScript 引擎看到行首是function关键字之后,认为这一段都是函数的定义,不应该以圆括号结尾,所以就报错了。

    解决方法就是不要让function出现在行首,让引擎将其理解成一个表达式。最简单的处理,就是将其放在一个圆括号里面。

    (function(){ /* code */ }()); // 或者 (function(){ /* code */ })();

    数组

    数组是特殊的对象,键名为数字 0—

    length很特殊,其默认值为最大的数字键名+1.如果添加字符串的键名,length的值是不会变的。

    length不过滤空位。

    如果在数组

    方法:

    Array.isArray() 返回是否为数组

    valueOf方法是一个所有对象都拥有的方法,表示对该对象求值。不同对象的valueOf方法不尽一致,数组的valueOf方法返回数组本身。

    toString方法也是对象的通用方法,数组的toString方法返回数组的字符串形式。

    push() 末尾添加新元素,并返回数组长度

    pop() 删除最后一个元素,并返回该元素

    shift() 删除第一个元素,~

    unshift() 数组第一个位置添加元素,并返回数组长度

    join()方法以指定参数作为分隔符,将所有数组成员连接为一个字符串返回。如果不提供参数,默认用逗号分隔。

    通过call方法,这个方法也可以用于字符串或类似数组的对象。

    Array.prototype.join.call('hello', '-') // "h-e-l-l-o" var obj = { 0: 'a', 1: 'b', length: 2 }; Array.prototype.join.call(obj, '-') // 'a-b'

    concat方法用于多个数组的合并。它将新数组的成员,添加到原数组成员的后部,然后返回一个新数组,原数组不变。

    如果数组成员包括对象,concat方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。

    var obj = { a: 1 }; var oldArray = [obj]; var newArray = oldArray.concat(); obj.a = 2; newArray[0].a // 2

    上面代码中,原数组包含一个对象,concat方法生成的新数组包含这个对象的引用。所以,改变原对象以后,新数组跟着改变。

    reverse方法用于颠倒排列数组元素,返回改变后的数组。注意,该方法将改变原数组。

    slice()方法用于提取目标数组的一部分,返回一个新数组,原数组不变。上面代码中,最后一个例子slice()没有参数,实际上等于返回一个原数组的拷贝。如果slice()方法的参数是负数,则表示倒数计算的位置。

    splice()方法用于删除原数组的一部分成员,并可以在删除的位置添加新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组。splice的第一个参数是删除的起始位置(从0开始),第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素。

    sort方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变。

    如果想让sort方法按照自定义方式排序,可以传入一个函数作为参数。

    map方法将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回。

    forEach方法与map方法很相似,也是对数组的所有成员依次执行参数函数。但是,forEach方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用map方法,否则使用forEach方法。 forEach方法不会跳过undefined和null,但会跳过空位。

    filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。

    reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样。

    indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1。

    正则表达式

    修饰符

    i 不区分大小写

    g 全局匹配

    一个正则表达式可以有多个修饰符吗?

    量词

    + 若干个

    {n} 正好出现几次

    {n, m} n-m次

    {n, }最少n次

    ?=={0,1}

    * {0,}任意次尽量不要用

    //其中?的使用拿固定电话前缀举例 (0\d{2,3}-)?[1-9]\d{7}(-\d{1,5})? //邮箱匹配 //一串英文、数字、下划线 @ 一串英文、数字 .一串英文 //当^ 不出现在括号内,表示行首,$表示行尾 (\w+@[a-z0-9]+\.[a-z]) var reg = /^\w+@[a-z0-9]+\.[a-z]$/ var str = '1294343193@qq.com' var valEmail = function(str){ if(reg.test(str)){ console.log('It\'s a right email address.') } else { console.log('It\'s a wrong email address.') } } valEmail('123444')

    表达式

    [ab] 查找包含方括号内字符的字符串

    [a-f] 查找a-f的字符

    ^ 除此之外

    转义字符

    \d ==[0-9] 0-9的任意一个数字

    \D ==[^ 0-9 ] 除了0-9之外的所有字符

    . 任意字符(尽量不要使用)

    \w 英文、数字、下划线 [a-z0-9_]

    \W 除了

    \s 空白字符

    \S 非空白

    var str = 'abg abc pcbgbf' var reg1 = /[ab][c-g]/g var reg2 = /[ab][cg]/g str.match(reg1) // ["bg", "bc", "bg", "bf"] str.match(reg2) // ["bg", "bc", "bg"]

    结合字符串方法

    search

    var regex = new RegExp('xyz', 'i'); var val = 'Xyzdew' val.search(regex)

    match

    var reg = /\d/g //\d==[0-9] var a = '123 3 2 ))))1====' var result = a.match(reg) // ["1", "2", "3", "3", "2", "1"] var reg1 = /\d+/g //\d==[0-9] var result = a.match(reg1) // ["123", "3", "2", "1"]

    replace

    敏感词过滤 var reg =/淘宝|百度/g var str = '淘宝是百度待定' var txt = str.replace(reg,'***'); //"***是***待定" 去除html标签 标签规则:<除了<>之外任意字符> var reg =/<[^<>]+>/g var str ='<li><a href="//www.runoob.com/">首页</a></li><li><a href="/html/html-tutorial.html">HTML</a></li>' txt = str.replace(reg,'') //"首页HTML"

    String对象

    实例方法

    charAt方法返回指定位置的字符,参数是从0开始编号的位置。

    charCodeAt()方法返回字符串指定位置的 Unicode 码点(十进制表示),相当于String.fromCharCode()的逆操作。

    concat方法用于连接两个字符串,返回一个新字符串,不改变原字符串。

    slice方法用于从原字符串取出子字符串并返回,不改变原字符串。它的第一个参数是子字符串的开始位置,第二个参数是子字符串的结束位置(不含该位置)。

    类型判断

    js作为一种动态类型的语言,虽然没有类型判断会有很多好处,但是往往会造成不必要的麻烦。所以,ts最重要的是提供了类型判断。

    那么,js本身又提供了哪些类型判断呢?

    首先列出要判断的类型:

    Number, String, Boolean,Object,Array, Json, Function, undefined, Null, Date, RegExp, Error

    typeof

    缺点,只能区分基本数据类型(number string boolean object),剩余的均被检测为object

    其中的特殊类型:

    null 是 object类型

    NaN 是number类型

    使用new的时候,new Function返回的类型是function; 其他的返回类型均为object

    instanceof

    undefined和null检测为object

    对于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; 这样定义是检测不出来的

    作用:

    1:识别对象类型;

    2:判断一个对象是否属于某个构造函数的实例

    语法:变量名 instanceof 数据类型 || 实例对象名 instaneof 构造函数

    原理: 左边是一个实例对象,右边是一个构造函数,instanceof会检查构造函数的原型对象prototype是否在左边对象的原型链上,有则返回true,否则返回false.

    内部代码:

    instanceof (A,B) = { var L = A.__proto__; var R = B.prototype; if(L === R) { //A的内部属性__proto__指向B的原型对象 return true; } return false; }

    constructor

    判断所有数据类型

    语法:变量名.constructor === 数据类型

    str.constructor===String //true num.constructor===Number //true obj.constructor===Object //true arr.constructor===Array //true new Date().constructor===Date //true f.constructor === Boolean

    constructor指向的构造函数可以被修改。

    Object.prototype.toString()

    https://www.jianshu.com/p/e4237ebb1cf0 看的不是很懂

    function *()
    Processed: 0.014, SQL: 9