JavaScript门道之数据类型

目录
1.数值
2.字符串
3.布尔值
4.undefined和null
5.对象
6.数组
7.函数
8.类型转换

1.数值

  • 数值表示:整数;小数;科学计数法;各种进制
123//123
123E3//123000
1.222//1.222
  • 数值的进制
111//十进制111
0b111//二进制7
0o111//八进制73
0x111//十六进制273
  • NaN:表示Not a Number,不是一种独立的数据类型,而是一种特殊数值,它的数据类型依然属于Number,只不过数值计算时不符合计算法则
0/0//NaN
Math.sqrt(-5)//NaN

判断NaN的方法

isNaN(NaN) // true
isNaN(123) // false

【注意】该方法只对数值有效,传入其他值先会转为NaN,最后返回true

2.字符串

  • 字符串的定义

字符串是由空字符或多个字符组合在一起的字符集合,使用时必须放在引号中,建议统一使用双引号,一方面既能够和HTML语言的属性值统一风格,又能够在在后面的JSON中匹配语法风格的烦恼

var a="hello world"
var b='hello javascript'
  • 使用'+'连接多个字符串
  • 转义字符

转义字符是指通过反斜杠""能够使得一些特殊字符还原成原来的意义
常见的有:
\t -> 制表符
\n -> 换行符
' -> '
" -> "
\ ->
\0 ->null

  • 字符串与数组
    可以使用数组的下标去读字符串中的特定字符,但不可以修改字符串,并且下标超过字符串长度时返回undefined
  • 字符串的属性与方法
    • length属性:返回字符串中的字符数目
var a="hello world"
console.log(a.length)//11
  • split方法:把字符串分割为字符串数组
var a="1234";
a.split("")//["1","2","3","4"]

3.布尔值

布尔值存在true和false两种值状态,出现布尔值的场景有:
逻辑运算(&& || !)
相等运算(=== === == !==)
比较运算(> >= < <=)
部分语句:条件语句和循环语句

【注意】y以下值均返回false

4.undefined和null

null是一个表示"无"的对象,转为数值时为0;
undefined是一个表示"无"的原始值,转为数值时为NaN。


也就是说:关于null和undefined的使用场景,object初始化时最好使用null,而基本数据类型最好使用undefined ,但是二者在本质上是没有区别的,是JS的一个bug!

5.对象

object:所谓对象,就是一种无序的数据集合,由若干个“键值对”(key-value)构成

  • 对象的创建方法
// 方法1
var hero={
  name: teren;
  age: 18;
  skill: battle;
}
// 方法2
hero = new Object();
hero.name="teren";
hero.age="18";
hero.skill="battle";
//方法3
function hero(name,age,skill){
  this.name=name;
  this.age=age;
  this.skill=skill;
}
var AmericanCaptain=new hero("teren",18,"battle")
console.log(AmericanCaptain)
  • 创建对象的属性并赋值/对象属性的引用与修改
//创建对象的属性并赋值
var hero={}
hero.name="teren";
hero.age=18;
hero["skill"]="battle";
hero["nickname"]="stone"
hero.height="";
console.log(hero)

//对象属性的引用与修改
hero.name;
hero["age"];
hero.height=180
  • 创建对象的方法
//创建对象的方法
function person(name,age){
  this.name=name;
  this.age=age;
  this.changeName=changeName;
  function changeName(name){
     this.name=name;    
  }
}
var myMother = new person("sunny",18);
// console.log(myMother)
myMother.changeName("windy")
console.log(myMother.name)

【注】

键名本质上都是字符串,实际创建键名时可以省略引号,但是为了符合JSON的语法规范,建议用上双引号,此外在使用objectName["propertyName"]必须加上引号

  • 检查属性是否在对象中的方法
var hero = {
   "name" : "teren",
   "age" : 18
}
"name" in hero//true
"skill" in hero//false

【小应用】

有这么个需求:如何检验一个变量是全局变量
基本知识:

  • 全局变量是window的属性
  • 属性未声明而直接引用不报错,而显示undefined,但变量未声明而使用就报错
a//a is not defined
window.a//undefined
//检测一个变量是否为全局变量
if (window.a === undefined){
   console.log("a是全局变量") 
}
  • 对象的遍历
var hero = {
  "name" : "teren",
  "age" : 18,
  "skill" : "battle"
}
for (var key in hero){
  console.log(key+":"+hero[key])
}
  • 对象的valueof ()和 toStringof ()方法

6.数组

数组:一种特殊的对象,是按次序排列的一组值

  • 数组的创建并赋值
//数组的创建并赋值
var a=new Array(1,2,3,4,5);
var b=["a","b","c"]
  • 访问数组元素与修改
//访问数组元素与修改
a[2]//3
b[0]//a
a[2]=8//
b[0]="hello"
  • 删除数组
var b=["a","b","c"]
b[0]="hello"
delete b[0]//b[0]显示为undefined
  • 数组与对象的关系
var a=new Array("hello",1,"world")
var b={
  "0" : "hello",
  "1" : 1,
  "2" : "world",
  "length" : 2
}
a[0]//"hello"
b[0]//"hello"
a[1]//1
b[1]//1
a.length//3
b.length//3
  • 数组的遍历
var a = new Array("hello",1,"world")
var i;
for (i=0;i<a.length;i++){
  console.log("a"+"["+i+"]"+":"+a[i])
}
  • 数组的常用方法
var a = new Array("hello",1,"world")
//push()方法可向数组末尾添加1个或多个元素,并返回新的数组长度
a.push(2)//4
//unshift()方法可以向数组开头添加1个或多个元素,并返回新的数组长度
a.unshift(3)
//pop()方法用于删除并返回数组最后一个元素,如果数组已经为空,则 pop() 不改变数组,并返回 undefined 值。
a.pop()//"world"
//a.shfit()方法数组的第一个元素删除,并返回第一个元素的值
a.shfit()
//a.join()方法是把数组中的所有元素放入一个字符串,并通过分隔符把所有元素隔开,分隔符的类型是可选的
a.join("---");//"3---hello---1"
a.join(".");//"3.hello.1"
//a.concat()方法是用于连接两个以上的数组
var b=[3,3,3]
a.concat(b)//["hello", 1, "world", 3, 3, 3]
//a.reverse()方法用于颠倒数组元素的顺序
a.reverse()//["world", 1, "hello"]
//a.splice(1,1,"a","b","c")方法表示从数组元素的第1个开始删除1个元素,并紧跟着添加3个元素,并返回删除值
a.splice(1,1,"a","b","c")//1,此时数组a的元素为["hello","a","b","c","world"]
//toString()方法是把数组元素返回字符串,并用逗号分隔
a.toString()//"hello,1,world"

7.函数

函数是一个特殊的对象,是代码块,可以被调用,可以输入参数并返回值

  • 函数的声明
//function命令
function fn(){
  var a=1;
  console.log(a)
}
//函数表达式
var a = function(){
  var b=1;
  console.log(b)
};
【注意】函数表达式在花括号最后必须加上分号,function命令可以不用,为了统一起见,最好统一使用分号结束语句
此外,但存在var fn=function f(){};时,这个函数名f只能在函数体内部调用,而在外部是无效的
//构造函数
var c = new Function("x","y","return (x+y)");
fn();
a();
console.log(c(1,2))

【注意】

  • 函数的声明不能在非函数的代码块下
  • function命令和函数表达式在变量提升层面存在一定的差异,function fn(){}是整块跟着提升,而var a=function(){}则是只提升var a
例如:下面写法不符合规范
if(true){
  function fn(){
    }
}
  • 函数的调用与函数的赋值
function fn(){
  var a=1;
  console.log(a)
}
//函数的调用:直接函数名+圆括号
fn();
//函数的赋值
var b =fn;
typeof b//function
  • 函数的属性与方法
    • name属性:返回紧跟在function关键字之后的函数名
function fn(){};
var fn2 = function(){};
var fn3 = function f(){};
fn.name;//fn
fn2.name;//""
fn3.name;//f
  • length属性:返回函数定义的参数个数
function fn(x,y,z){};
var fn2 = function(a1,a2){};
var fn3 = function f(name){};
fn.length//3
fn2.length//2
fn3.length//1
  • toString()方法:返回函数的源码
function fn(){
  //这是函数的toString()方法
  console.log(a);
}
//返回内容为:"function fn(){
//这是函数的toString()方法
//console.log(a);
//}"
  • 关于命名冲突
    当在同一个作用域内定义了名字相同的变量和方法的话,无论其顺序如何,变量的赋值会覆盖方法的赋值
var fn = 3;
function fn(){
console.log(fn)
}; // 3
  • 函数的作用域

作用域是指变量存在的范围,可分为全局作用域和函数作用域,由此可划分变量为全局变量和局部变量

  • 全局作用域:变量作用范围是全局,直到js运行失效
  • 函数作用域:变量作用分为是函数内部,函数执行完后就失效
  • 作用域链:JavaScript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量
var a = 1;
function fn(){
  var b = 2;
  c=3;
  console.log(a+b)
}
b//b is not defined
//a是全局变量,只要js运行都会生效;
//b是局部变量,只在函数体内部生效;
//注意如果函数内部的变量不加var声明,那么会当做全局变量
  • arguments对象
    我们知道函数可以添加参数,而arguments对象包含了函数运行时的所有参数,但这个对象只能在函数体内部使用
function fn(a,b,c,d){
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
  console.log(arguments[3]);  
}
fn(1,2,3,4);//1 2 3 4
//使用arguments.length属性得知参数的个数
function fn2(){
  console.log(arguments.length);
}
fn2(1,2,3,4)//4

【注意】与其他程序设计语言不同,ECMAScript 不会验证传递给函数的参数个数是否等于函数定义的参数个数。开发者定义的函数都可以接受任意个数的参数(根据 Netscape 的文档,最多可接受 255 个),而不会引发任何错误。任何遗漏的参数都会以 undefined 传递给函数,多余的函数将忽略。

function fn(a,b,c){
  console.log(a+b+c);
}
// 定义3个参数,即便传入超过3个参数函数还是生效
fn(1,2,3,4,5)//6
fn(1,"",3);//"13"
function fn2(a,b){
  return a;
}
// fn(,3)//报错Unexpected token
//如果需要某个中间参数缺失,需显式传入undefined
fn2(undefined,3)//undefined
  • 立即执行函数
    • 什么是立即执行函数
      一种声明之后就立即进行该函数执行操作的匿名函数
    • 立即执行函数的写法
      function()前面加任意符号,告诉js引擎这是要执行函数而不是声明函数,注意最后必须加分号
    • 为什么要用立即执行函数
      消除全局变量的污染;
      防止其他js文件出现与本文件的函数名重名情况,那么函数内部定义的同一个变量a有可能被污染;
      IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
    • 立即执行函数应用
      待续
  • 闭包
    详情请见javaScript门道之闭包

8.类型转换

JS是一门动态类型的语言,var不显示数据类型,但是数据本身和各种运算符是有类型的

  • 强制转换
    Number()方法:转成数值
Number("333")//333
Number("333aaa")//NaN
Number(true)//1
Number(false)//0
Number("")//0
Number(undefined)//NaN
Number(null)//0
Number({a:1})//NaN
Number([1,2,3])//NaN

String()方法:转成字符串

String(123)//"123"
String(true)//"true"
String(undefined)//"undefined"
String(null)//"null"
String({})//"[object Object]"
String([1,2,3])//"1,2,3"

Boolean()方法:转成布尔值
除了以下5种,其他都是true

undefined
null
""
0
NaN

关于转成布尔值的方法,也可以使用!!

!!123//true
!!undefined//false,等价于Boolean(undefined)
  • 自动转换
    自动转换的规则是这样的:预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用String函数进行转换。
    由于自动转换具有不确定性,而且不易除错,建议在预期为布尔值、数值、字符串的地方,全部使用Boolean、Number和String函数进行显式转换。

    • 自动转换为数值,常用-0将其他类型的数据转换为数值
"1"-0//1
"hello"-0//NaN
true-0//1
//当然任何类型数据可以和除了+以外的算术运算符都可以自动转化为数值
"1"/2//0.5

【注意】
当JavaScript遇到预期为数值的地方,就会将参数值自动转换为数值。系统内部会自动调用Number
函数。
除了加法运算符有可能把运算子转为字符串,其他运算符都会把运算子自动转成数值

  • 自动转换为字符串,常出现于和运算符+
"h"+1//"h1"
"h"+true//"htrue"
"h"+undefined//"hundefined"
"h"+null//"hnull"
"h"+NaN//"hNaN"
"t"+{}//"t[object Object]"
"t"+[]//"t"
"t"+function(){}//"tfunction(){}"

【注意】
当JavaScript遇到预期为字符串的地方,就会将非字符串的数据自动转为字符串。系统内部会自动调用String
函数。
可以利用这一特性,将任何数据类型转换为字符串,""+数据类型值

  • 自动转换为布尔值:常见于条件语句
var a;
if (undefined){
  console.log(a=1);
}else {
  console.log(a=2)
}//2
!!null ? a=1 : a=2;//a=2

【注】以上内容整理主要出自阮一峰的技术博客、饥人谷导师的教学资源以及一些网络资料

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

推荐阅读更多精彩内容

  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,622评论 2 17
  • 函数声明和函数表达式有什么区别 (*)解析器会率先读取函数声明,并使其在执行任何代码之前可以访问;函数表达式则必须...
    coolheadedY阅读 371评论 0 1
  • 原文: https://github.com/ecomfe/spec/blob/master/javascript...
    zock阅读 3,343评论 2 36
  • 每个人的外表 没什么太大的区别 总会被认出是人类 也总会被认错职业形形色色的我们 其实头脑里的东西 才是最让人看不...
    想睡懒觉的老少女阅读 167评论 0 0
  • (如需转载,请提前告知) 有雪的地方就有关于雪的种种传说,过去的人并不知道这只是一种气象现象,四季中只有冬季会出现...
    阿尔法酱阅读 3,642评论 14 96