JS中的七种数据类型

js中有七种数据类型,包括基本数据类型 Number、String、Boolean、Undefined、Null、Symbol(ES6 新增,创建后独一无二且不可变的数据类型),一种复杂数据类型( Object )。
由于js中的变量是松散类型多的,所以它提供了一种检测当前变量的数据类型的方法,也就是 typeof 关键字。

typeof 123            // Number
typeof 'abc'          // String
typeof true           //Boolean
typeof undefined      //Undefined
typeof null           //Object
typeof {}             //Object
typeof []             //Object
let a = function() {
  console.log(1)
}
typeof a               //function
let s = Symbol();
typeof s    //symbol

null类型进行typeof操作符后,结果是object,原因在于,null类型被当做一个空对象引用。

1.Number

Number类型包含整数和浮点数两种值。
NaN:非数字类型。特点:涉及到的任何关于NaN的操作,都会返回NaN;NaN不等于自身。
isNaN()函数用于检查其参数是否是非数字值。

isNaN(123)       //false
isNaN("hello")   //true

2.String

字符串有length属性。
字符串转换:
String():适合于任何数据类型(null,undefined转换后为null和undefined);
toString()方法:括号中的可以写一个数字,代表进制,对应进制字符串,null、defined没有toString()方法。

3.Boolean

该类型只有两个值,true和false。

4.Undefined

只有一个值,即undefined值。使用var声明了变量,但未给变量初始化值,那么这个变量的值就是undefined。

5.Null

null类型被看做空对象指针,前文的null类型也是空的对象引用。

6.Symbol

Symbol是ES6新增的原始数据类型,是为了解决在对象中对属性名滥用而导致的冲突问题。
ps:既然是数据类型,不是对象,那么就不能用new命令,因此不能添加属性。

let a = Symbol('a');
console.log(a);        //Symbol(a)
console.log(typeof a)  //symbol
简单来说:一旦声明一个变量为symbol类型,说明这个变量是唯一的,独一无二的,覆盖不了的。
let a = Symbol('abc');
let b = Symbol('abc');
let c = 'abc';
let d = 'abc';
console.log(a === b)   //false
console.log(c === d)   //true

现在,在对象的属性名有两种类型,一个是以字符串的形式,另一个是以Symbol的形式
若以symbol的形式去写,那么就要按照规范去写,加上中括号[],来表明使用了symbol类型,获取时而不是按照字符串类型的属性名去获取,而以中括号获取。

let name = Symbol();
let obj = {
  [name]: 'black',
  age: 25,
  name: 'red'
}
console.log(obj)  //{age: 25,name: "red",Symbol(): "black"}

通过例子可知:获取对象时,得到是两个不一样的name属性名,说明symbol和字符串时两种不一样的值,获取方式也不一样,按照点获取的是字符串,中括号获取的是symbol类型的值。
关于在对象声明时对symbol类型的写法有三种:

let sym = Symbol();
//第一种写法:
let a = {};
a[sym] = 'hello';
console.log(a);   //{Symbol(): "hello"}

//第二种写法:
let a = {
  [sym]: 'hello'
}
console.log(a);   //{Symbol(): "hello"}

//第三种写法:
let a = {};
Object.defineProperty(a, sym, {value: "hello"});
console.log(a);

实例:

const shapeType = {
    triangle: Symbol(),
    rectangle: Symbol(),
};

function getArea(shape, options) {
    let area = 0;
    switch (shape) {
        case shapeType.triangle:
        area = .5 * options.width * options.height;
        break;
        case shapeType.rectangle:
        area = options.width * options.height;
        break;
    }
    return area;
}

let a = getArea(shapeType.triangle, { width: 100, height: 100 });
let b = getArea(shapeType.rectangle, { width: 100, height: 100 });
console.log(a)   // 5000
console.log(b)   // 10000

Symbol方法:
Object.getOwnPropertySymbols()返回一个数组,成员是当前对象的所有用作属性名的Symbol值。
symbol在对象上作为一个属性名,不会被循环的方法所识别,不会出现在for...in、for...of循环中,不会被Object.keys()、Object.getOwnPropertyNames()、JSON.stringify()返回,所以它有自己获取symbol值的方法。

let name = Symbol('name');
let age = Symbol('age')
let obj = {
   [name]: 'peter',
   [age]: 25
}
let a = Object.getOwnPropertySymbols(obj)
console.log(a)    // [Symbol(name), Symbol(age)]

Reflect.ownKeys() 返回所有类型的键名,包括常规键名和 Symbol 键名

let name = Symbol('name');
let obj = {
    [name]: 'peter',
    age: 25,
    enum: 2
}
console.log(Reflect.ownKeys(obj))    // ["age", "enum", Symbol(name)]

Symbol.for() 接受一个字符串作为参数,然后搜索有没有以该参数作为名称的 Symbol 值。如果有,就返回这个 Symbol 值,否则就新建并返回一个以该字符串为名称的 Symbol 值。
这个方法就是重新使用已有symbol的值,在遍历判断时常用 。

let a = Symbol.for('abc');
let b = Symbol.for('abc');
let c = Symbol.for('ab');
console.log(a === b)    // true
let a = Symbol.for('abc') 
let b = Symbol('abc')
console.log(a)   // Symbol(abc)
console.log(a === b)   // false

由此可知:a虽然用Symbol.for声明了symbol类型,但是却和symbol声明不一样,说明两者不是同一个值。

Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。

let s1 = Symbol('foo');
let s2 = Symbol('bar');

s1 //Symbol(foo)
s2 //Symbol(bar)

s1.toString();  //"Symbol(foo)"
s2.toString();  //"Symbol(bar)"

上面代码中,s1和s2是两个Symbol值。如果不加参数,他们在控制台输出都是Symbol(),不利于区分。有了参数以后,就等于为它们加上了描述,输出的时候就能够分清,到底是哪一个值。

如果Symbol的参数是一个对象,就会调用该对象的toString方法,将其转为字符串,然后生成一个Symbol。

const obj = {
  toString() {
    return 'abc'
  }
}
const sym = Symbol(obj);
sym //Symbol(abc)

注意,Symbol函数的参数只是表示对当前Symbol值的描述,因此相同参数的Symbol函数的返回值是不相等的。

// 没有参数的情况
let s1 = Symbol();
let s2 = Symbol();
s1 === s2  //false

//有参数的情况
let s1 = Symbol('foo');
let s2 = Symbol('foo');
s1 === s2 //false

上面代码中,s1和s2都是Symbol函数的返回值,而且参数相同,但是它们是不相等的。

Symbol 值不能与其他类型的值进行运算,会报错。

let sym = Symbol('My symbol');
"you symbol is"+sym
// Uncaught TypeError: Cannot convert a Symbol value to a string
`your symbol is ${sym}`
// TypeError: can't convert symbol to string

但是,Symbol 值可以显式转为字符串。
let sym = Symbol('My symbol');
String(sym) // 'Symbol(My symbol)'
sym.toString() // 'Symbol(My symbol)'

另外,Symbol值可以转变为布尔值,但是不能转为数值。

let sym = Symbol();
Boolean(sym)  //true
!sym  //false

if(sym){
  //...
}

Number(sym)  //TypeError
sym+2       //TypeError

7.Object

js中对象是一组属性与方法的集合。这里就要说到引用类型了,引用类型是一种数据结构,用于将数据和功能组织在一起。引用类型有时候也被称为对象定义,因为它们描述的是一类对象所具有的属性和方法。
三大引用类型:
1.Object类型
我们看到的大多数类型值都是Object类型的实例,创建Object实例的方式有两种:
第一种是使用new操作符后跟Object构造函数,如下所示:

var person = new Object();
person.name = "托尼老师";
person.age = 24;

第二种方式是使用对象字面量表示法,如下所示:

var person = {
  name: '托尼老师',
  age: 24
}

2.Array类型
数组的每一项都可以用来保存任何类型的数据,也就是说,可以用数组的第一个位置来保存字符串,第二个位置保存数值,第三个位置保存对象...另外,数组的大小是可以动态调整的。
创建数组的基本方式有两种:
第一种是使用Array构造函数,如下所示:

var colors = new Array("red","blue","yellow");

第二种是使用数组字面量表示方法,如下所示:

var colors = ["red","blue","yellow"];

3.function类型
每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。函数通常是使用函数声明语法定义的,如下所示:

function sum(num1,num2){
  return num1 + num2;
}

这和使用函数表达式定义函数的方式相差无几。

var sun = function(){
  return sum1 + sum2;
}

也就是说,js按照存储方式分为值类型和引用类型。他们计算有什么区别呢?
题目1:

var a = 100;
var b = a;
a =200;
console.log(b);    //100

题目2:

var a = {age : 20};
var b = a;
b.age = 21;
console.log(a.age);   //21

题目一是简单的值类型,在从一个变量向另一个变量赋值基本类型时,会在该变量上创建一个新值,然后再把该值复制到为新变量分配的位置上。
此时,a中保存的值为100,当使用a来初始化b时,b中保存的值也为100,但b中的100与a中的是完全独立的,该值只是a中的值的一个副本,此后,这两个变量可以参加任何操作而不受影响。就是说基本类型在赋值操作后,两个类型是相互不受影响的。

题目2是引用类型,当从一个变量向另一个变量赋值引用类型的值时,同样也会将存储在变量中的对象的值赋值一份放到为新变量分配的空间中。
这时保存在变量中的对象是堆内存中的地址,所以,与简单赋值不同,这个值的副本实际上是一个指针,而这个指针指向存储在堆内存的一个对象。那么赋值操作后,两个变量都保存了同一对象地址,则这两个变量指向了同一个对象,因此,改变其中任何一个变量,都会相互影响。
因此,引用类型的赋值其实是对象保存在栈区地址指针的赋值,所以两个变量指向同一个对象,任何的操作都会相互影响。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,132评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,802评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,566评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,858评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,867评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,695评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,064评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,705评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,915评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,677评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,796评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,432评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,041评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,992评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,223评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,185评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,535评论 2 343

推荐阅读更多精彩内容

  • 函数和对象 1、函数 1.1 函数概述 函数对于任何一门语言来说都是核心的概念。通过函数可以封装任意多条语句,而且...
    道无虚阅读 4,521评论 0 5
  • 第3章 基本概念 3.1 语法 3.2 关键字和保留字 3.3 变量 3.4 数据类型 5种简单数据类型:Unde...
    RickCole阅读 5,096评论 0 21
  • 0. 写在前面 当你开始工作时,你不是在给你自己写代码,而是为后来人写代码。 —— Nichloas C. Zak...
    康斌阅读 5,297评论 1 42
  • 立志用功,如树使然。 方其根芽,犹未有干; 及其有干,尚未有枝。 枝而后叶,叶而后花、实。 初种根时,只管栽培灌溉...
    花开兮缓归阅读 1,094评论 0 0
  • 晚上翻来覆去,哀叫着说不舒服,室友递给了我一版药,我喝完药就想睡了。就是晚上睡觉太难受了,鼻塞,咽炎,折磨死人,不...
    我叫小屁孩阅读 212评论 0 0