Web全栈-JavaScript-笔记1-数据类型

一:浅聊前端发展史

第一阶段:C/S(client server) -> B/S(browser server) 网页制作
技术栈:PhotoShop、HTML、CSS

第二阶段:从静态到动态,从后端到前端 前端开发工程师
前后端分离
后台:完成数据的分析和业务逻辑编写(包含API接口编写)
前端:网页制作、JS交互效果、数据的交互和绑定

技术栈:JavaScript、AJAX(跨域技巧)、jQuery...

第三阶段:从前端到全端(从PC端到移动端)
技术栈:H5、CSS3、响应式布局开发、Zepto、Hybrid(混合APP开发)、微信小程序...

第四阶段:从全端到全栈
全栈开发:前后端都可以开发(严格意义讲,一种语言完成前后端开发)
技术栈:NODE(基于JS编程语言开发服务器端程序)、Express/Koa...

为了迎合日益发展的前端开发,JS中诞生很多有助于开发、维护、提高性能的框架:Vue、React、Angular、webpack...

展望WEB4.0时代,VR/AR元年,前端需要Canvas/webGL...


二、关于浏览器的内核和引擎

webkit(v8引擎):大部分浏览器
gecko:火狐
trident:IE
...

W3C:万维网联盟,制定编程语言的规范与标准
开发者按照规范编写代码,浏览器开发商也会开发一套按照规范把代码渲染成页面的东西(这个东西就是内核或者引擎)

浏览器内核作用:按照一定的规范,把代码基于GPU(显卡)绘制出对应的图形和页面等

为啥会出现浏览器兼容:
1.部分浏览器会提前开发一些更好的功能,后期这些功能会被收录到W3C规范中,但是在收录之前,会存在一定的兼容性
2.各个浏览器厂商,为了突出自己的独特性,用其它方法实现了W3C规范中的功能
...


三、JavaScript

JS:轻量级的客户端脚本编程语言

  1. 编程语言
    HTML+CSS是标记语言
    编程语言是具备一定逻辑的,拥有自己的编程思想(面向对象编程 [OOP]、面向过程编程)
  • 面向对象
    • C++
    • JAVA
    • PHP
    • C#(.net)
    • JS
    • ...
  • 面向过程
    • C
  1. 目前的JS已经不仅仅是客户端语言了,基于NODE可以做服务器端程序,所以JS是全栈编程语言

  2. 学习JS,我们学习它的几部分组成

    • ECMAScript(ES):JS的核心语法
    • DOM:document object model 文档对象模型,提供各种API(属性和方法)让JS可以获取或者操作页面中的HTML元素(DOM和元素)
    • BOM:browser object model 浏览器对象模型,提供各种API让JS可以操作浏览器

四:ESMAScript

它是JS的语法规划,JS中的变量、数据类型、语法规范、操作语句、设计模式等等都是ES规定的


五:变量(variable)

它不是具体的值,只是一个用来存储具体值的容器或者代名词,因为它存储的值可以改变,所以称为变量

基于ES语法规范,在JS中创建变量有以下方式

  • var (ES3)
  • function (ES3) 创建函数(函数名也是变量,只不过存储的值是函数类型的而已)
  • let (ES6)
  • const (ES6) 创建的是常量
  • import (ES6) 基于ES6的模块规范导出需要的信息
  • class (ES6) 基于ES6创建类
/*
 * 语法:
 *   var [变量名]=值
 *   let [变量名]=值
 *   const [变量名]=值
 *   function 函数名(){
 *
 *   }
 *   ...
 */
var n = 13;
n = 15;
alert(n+10);//=>弹出来25 此时的N代表15

const m = 100;
m = 200;//=>Uncaught TypeError: Assignment to constant variable. 不能给一个常量重新的赋值(常量存储的值不能被修改,能够修改就是变量了)

创建变量,命名的时候要遵循一些规范

  • 严格区分大小写
  • 遵循驼峰命名法:按照数字、字母、下划线或者$来命名(数字不能做为名字的开头),命名的时候基于英文单词拼接成一个完整的名字(第一个单词字母小写,其余每一个有意义单词的首字母都大写)
  • 不能使用关键字和保留字:在JS中有特殊含义的叫做关键词,未来可能会成为关键字的叫做保留字
var n=12;
var N=13; //=>两个n不是同一个变量

var studentInfo / student_info / _studentInfo(下划线在前的,都是公共变量) / $studentInfo(一般存储的是JQ元素)...

语义化强一些
  add / create / insert
  del(delete)/ update / remove(rm)
  info / detail
  log
  ...

六:值的类型

数据值是一门编程语言进行生产的材料,JS中包含的值有以下这些类型

  • 基本数据类型(值类型)
    • 数字number
    • 字符串string
    • 布尔boolean
    • null
    • undefined
  • 引用数据类型
    • 对象object
      • 普通对象
      • 数组对象
      • 正则对象
      • 日期对象
      • ...
    • 函数function
  • ES6中新增加的一个特殊的类型:Symbol,唯一的值
[基本数据类型]
var n = 13; 
// 0 -13 13.2 数字类型中有一个特殊的值NaN(not a number代表不是一个有效的数字,但是属于number类型的)

var s = '';
//"" '13' "{}" JS中所有用单引号或者双引号包裹起来的都是字符串,里面的内容是当前字符串中的字符(一个字符串由零到多个字符组成)

var b = true;
//布尔类型只有两个值 true真 false假



[引用数据类型]
var o = {name:'Web全栈', age:9}; //是对象数据类型 object
//普通的对象:由大括号包裹起来,里面包含多组属性名和属性值(包含多组键值对) {}空对象

var ary = [12, 23, 34, 45];  //object类型
//中括号包裹起来,包含零到多项内容,这种是数组对象  []空数组

var reg = /-?(\d|([1-9]\d+))(\.\d+)?/g;  //object类型
//由元字符组成一个完整的正则,//不是空正则是单行注释

function fn(){  //function数据类型

}

[Symbol]
创建出来的是一个唯一的值
var a = Symbol('全栈');
var b = Symbol('全栈');
a==b //=>false

扩展:JS代码如何被运行以及运行后如何输出结果
[如何被运行]

  • 把代码运行在浏览器中(浏览器内核来渲染解析)
  • 基于NODE来运行(NODE也是一个基于V8引擎渲染和解析JS的工具)

[如何输出结果]

  • alert:在浏览器中通过弹框的方式输出(浏览器提示框)
var num=12;
alert(num); //=>window.alert

var str='全栈';
alert(str);

基于alert输出的结果都会转换为字符串:
把值(如果是表达式先计算出结果)通过toString这个方法转换为字符串,然后再输出

alert(1+1); // =>'2'
alert(true); // =>'true'
alert([12,23]); // =>'12,23'
alert({name:'xxx'}); // =>'[object Object]' 对象toString后的结果就是object object,为啥?
  • confirm:和alert的用法一致,只不过提示的框中有确定和取消两个按钮,所以它是确认提示框
var flag = confirm('确定要退出吗?');
if(flag){
   //=>flag:true 用户点击的是确定按钮
}else{
   //=>flag:false 用户点击的是取消按钮
}
  • prompt:在confirm的基础上增加输入框

  • console.log:在浏览器控制台输出日志(按F12(FN+F12)打开浏览器的控制台)

    • Elements:当前页面中的元素和样式在这里都可以看到,还可以调节样式修改结构等
    • Console:控制台,可以在JS代码中通过.log输出到这里,也可以在这里直接的编写JS代码
    • Sources:当前网站的源文件都在这里
    • ...
  • console.dir:比log输出的更加详细一些(尤其是输出对象数据值的时候)

  • console.table:把一个JSON数据按照表格的方式输出

  • ... (自己扩展更多console输出方法)


七、数据类型的详细剖析

Number数字类型

  1. number数字类型
    number:正数、负数、0、小数、NaN
    NaN:not a number 但是它是Number数字类型的
    isNaN:检测当前值是否不是有效数字,返回true代表不是有效数字,返回false是有效数字
//=>语法:isNaN([value])
var num=12;
isNaN(num); //->检测num变量存储的值是否为非有效数字 false

isNaN('13') // =>false
isNaN('全栈') // =>true
isNaN(true) // =>false
isNaN(false) // =>false
isNaN(null) // =>false
isNaN(undefined) // =>true
isNaN({age:9}) // =>true
isNaN([12,23]) // =>true
isNaN([12]) // =>false
isNaN(/^$/) // =>true
isNaN(function(){}) // =>true

重要:isNaN检测的机制
1、首先验证当前要检测的值是否为数字类型的,如果不是,浏览器会默认的把值转换为数字类型

把非数字类型的值转换为数字

  • 其它基本类型转换为数字:
    直接使用Number()这个方法转换的
  [字符串转数字]
    Number('13') // ->13
    Number('13px') // ->NaN 如果当前字符串中出现任意一个非有效数字字符,结果则为NaN
    Number('13.5') // ->13.5 可以识别小数

  [布尔转数字]
    Number(true) // -> 1
    Number(false) // -> 0

  [其它]
    Number(null) // -> 0
    Number(undefined) // -> NaN
  • 引用数据类型值转换为数字:
    先把引用值调用toString转换为字符串,然后再把字符串调用Number转换为数字
   [对象]
     ({}).toString() // ->'[object Object]' ->NaN

   [数组]
     [12,23].toString() // ->'12,23' ->NaN
     [12].toString() // ->'12' ->12

   [正则]
     /^$/.toString() // ->'/^$/' ->NaN

  Number('') // ->0
  [].toString() // ->''
  => isNaN([]):false //[] -> '' - > 0

2、当前检测的值已经是数字类型,是有效数字返回false,不是返回true
(数字类型中只有NaN不是有效数字,其余都是有效数字)


除了Number()可以转换为数字,还有其他的函数也可以:
parseInt / parseFloat

等同于Number,也是为了把其它类型的值转换为数字类型

和Number的区别在于字符串转换分析上

Number:出现任意非有效数字字符,结果就是NaN

parseInt:把一个字符串中的整数部分解析出来,parseFloat是把一个字符串中小数(浮点数)部分解析出来

parseInt('13.5px') // =>13
parseFloat('13.5px') // =>13.5

parseInt('width:13.5px') 
// =>NaN 从字符串最左边字符开始查找有效数字字符,并且转换为数字,但是一但遇到一个非有效数字字符,查找结束

思考题:有一个变量num,存储的值不知道,我想检测它是否为一个有效数字,下面方案是否可以

if(Number(num)==NaN){
    alert('num不是有效数字!');
}

NaN和谁都不相等,条件永远不成立(即使num确实不是有效数字,转换的结果确实是NaN,但是NaN!=NaN的)

if(isNaN(num)){
    //=>检测是否为有效数字,只有这一种方案
    alert('num不是有效数字!')
}

布尔类型

只有两个值:true / false

如何把其它数据类型转换为布尔类型?

  • Boolean
  • !
  • !!
Boolean(1) // =>true

!'Web全栈' // =>先把其它数据类型转换为布尔类型,然后取反
![]  // 是false

!!null // =>去两次反,等价于没取反,也就剩下为转换为布尔类型了,相当于Boolean()

console.log(Boolean("zhangsan");
console.log(!!"zhangsan"); //这2个是一个意思。

规律:在JS中只有“0/NaN/空字符串""/null/undefined”这五个值转换为布尔类型的false,其余都转换为true

如果是两个值比较是否相等,遵循这个规则:
val1 == val2,两个值可能不是同一个数据类型的,如果是==比较的话,会进行默认的数据类型转换。

1)对象==对象
永远不相等
例如:

[]==[]   // false
({}=={}) // false

2)对象==字符串
先将对象转换为字符串(调用toString的方法),然后在进行比较。
[]转换为字符串""
{}转化为字符串"[object Object]"

3)对象==布尔类型
对象先转换为字符串(toString),然后把字符串在转化为数字(使用Number(), ""变成0),
布尔类型也转换为数字(true是1,false是0),最后让两个数字比较。

4)对象==数字
先将对象转化为字符串,再将字符串转化为数字,两个数字比较。

5)数字 == 布尔
布尔转化为数字,true为1,false为0

6)数字==字符串
字符串转化为数字

7)字符串==布尔
都转换为数字

8)null == undefined
结果是true

9)null或者undefined和其他任何的数据类型比较都不相等。

10)NaN == NaN

NaN==NaN:// false ,NaN和谁都不相等,包括自己
//左边NaN表示非数字里的任何一个,右边也表示非数字里的任何一个,所以它们比较不相等。

除了是比较,=也是比较(绝对比较)
val1 === val2 ,如果数据类型不一样肯定不相等。


null && undefined

都代表空或者没有

  • null:空对象指针
  • undefined:未定义

null一般都是意料之中的没有(通俗理解:一般都是人为手动的先赋值为null,后面的程序中我们会再次给他赋值)

var num = null; //=>null是手动赋值,预示着后面我会把num变量的值进行修改
...
num = 12;

undefined代表的没有一般都不是人为手动控制的,大部分都是浏览器自主为空(后面可以赋值也可以不赋值)

var num; //=>此时变量的值浏览器给分配的就是undefined
...
后面可以赋值也可以不赋值

object对象数据类型

普通对象

  • 由大括号包裹起来的
  • 由零到多组属性名和属性值(键值对)组成

对象数据类型,还可以具体的细分:
{}、[]、/^$/、时间。。。

对象类(Object)、数组类(Array)、正则类(RegExp)、时间类(Date)、字符串类(String)、布尔类(Boolean) 《这些都是类》
对应的实例就是 对象、数组、正则、时间。。。 《这些都是实例》

var obj = {};
var ary = [];
var reg = /^$/;

js中对象、类、实例的区别:对象是泛指,js中万物皆对象,类是对对象的具体的细分,实例是类中一个具体的事物。
举例:自然界中万物皆对象,所有的东西可以分为:人类、植物类、动物类、物体类,每一个人都是人类中一个具体的实例

实例才是对象数据类型。

属性是用来描述当前对象特征的,属性名是当前具备这个特征,属性值是对这个特征的描述(专业语法,属性名称为键[key],属性值称为值[value],一组属性名和属性值称为一组键值对)

var obj = {
	name:'Web全栈',
	age:9
}; //字面量创建方式

var obj = new Object(); //实例创建方式
obj.name = "zhangsan";
// obj.["name"] = "zhangsan";
obj["age"] = 6;

//=>对象的操作:对键值对的增删改查
语法:对象.属性 / 对象[属性]

[获取]
obj.name 
obj['name']  一般来说,对象的属性名都是字符串格式的(属性值不固定,任何格式都可以)
obj["name"]

[增/改]
JS对象中属性名是不允许重复的,是唯一的
obj.name='小明'; //=>原有对象中存在NAME属性,此处属于修改属性值
obj.sex='男'; //=>原有对象中不存在SEX,此处相当于给当前对象新增加一个属性SEX
obj['age']=28;

[删]
彻底删除:对象中不存在这个属性了
delete obj['age'];

假删除:并没有移除这个属性,只是让当前属性的值为空
obj.sex=null;

在获取属性值的时候,如果当前对象有这个属性名,则可以正常获取到值(哪怕是null),
但是如果没有这个属性名,则获取的结果是undefined
obj['friends'] // =>undefined

思考题:

var obj = {
	name:'Web全栈',
	age:9
};
var name = 'zhangsan';

obj.name  // =>'Web全栈'  获取的是name属性的值
obj['name'] // =>'Web全栈' 获取的是name属性的值
obj[name] // =>此处的name是一个变量,我们要获取的属性名不叫做name,是name存储的值'zhangsan' 
// =>obj['lisi'] =>没有这个属性,属性值是undefined

----
'name' 和 name 的区别?
//  => 'name'是一个字符串值,它代表的是本身
//  => name是一个变量,它代表的是本身存储的这个值

一个对象中的属性名不仅仅是字符串格式的,还有可能是数字格式的

var obj = {
	name:'Web全栈', //name加不加引号都是字符串形式
	0:100
};

obj[true] = 200; //是可以的,这里的 true 是 "true" 属性名
obj[null] = 300; // 类似的
obj[undefined] = 400;

obj[0] =>100
obj['0'] =>100
obj.0 =>Uncaught SyntaxError: Unexpected number

当我们存储的属性名不是字符串也不是数字的时候,浏览器会把这个值转换为字符串(toString),然后再进行存储

obj[{}]=300;  
// =>先把({}).toString()后的结果作为对象的属性名存储进来 
//相当于
obj['[object Object]']=300

obj[{}]  //300
// =>获取的时候也是先把对象转换为字符串'[object Object]',然后获取之前存储的300
obj[{xxx:'xxx'}]  //300
//{xxx:'xxx'}转为字符串也是 '[object Object]' 这个字符串,所以也是获得300

数组对象(对象由键值对组成的,数组对象的键是索引)

var ary = [12, 23]; //=>12和23都是属性值,属性名呢?

通过观察结果,我们发现数组对象的属性名是数字(我们把数字属性名称为当前对象的索引)
ary[0]
ary['0']
ary.0  // =>报错

数组是对象,对象有的操作,它都有。
ary[1]=230; //修改
ary[2]=340; //添加
ary['age']=10; //非数字形式的索引,也是可以的
//中括号语法不支持 var ary=[12, 23, age:'12']   但通过属性名方式是可以添加非数字形式的索引

//是否是数组,看__proto__属性是什么

不同数据类型的操作方式

//基本数据类型和引用数据类型的区别
var num1 = 12;
var num2 = num1;  //把num1变量代表的值给了num2变量
num2++; //相当于 num2 = num2 + 1; 在自己原有值的基础上加1
console.log(num1);
var obj1 = {n:100};
var obj2 = obj1;
obj2['n'] = 200;
console.log(obj1.n);

浅分析JS的运行机制

1、当浏览器(它的内核\引擎)渲染和解析JS的时候,会提供一个供JS代码运行的环境,我们把这个环境称之为“全局作用域(global/window scope)”

2、代码自上而下执行(之前还有一个变量提升阶段)
=>基本数据类型的值会存储在当前作用域下
var a = 12;
1)首先开辟一个空间存储12
2)在当前作用域中声明一个变量a (var a)
3)让声明的变量和存储的12进行关联(把存储的12赋值给a =>赋值操作叫做定义)

基本数据类型(也叫作值类型),是按照值来操作的:把原有的值复制一份,放到新的空间或者位置上,和原来的值没有关系

=>引用数据类型的值不能直接存储到当前的作用域下(因为可能存储的内容过于复杂),我们需要先开辟一个新的空间(理解为仓库),把内容存储到这个空间中
var obj1 = {n: 100};
1)首先开辟一个新的内存空间,把对象中的键值对依次存储起来(为了保证后面可以找到这个空间,此空间有一个16进制的地址)
2)声明一个变量
3)让变量和空间地址关联在一起(把空间地址赋值给变量)

引用类型不是按照值来操作,它操作的是空间的引用地址:把原来空间的地址赋值给新的变量,但是原来的空间没有被克隆,还是一个空间,这样就会出现多个变量关联的是相同的空间,相互之间就会存在影响了

练习题:

/*
 * 1、形成一个全局作用域(栈内存)
 * 2、代码自上而下执行
 *   1.首先开辟一个新的堆内存(AAAFFF111),把键值对存储到堆内存中
 *     n:10
 *     m:obj.n*10 =>obj.n 此时堆内存信息还没有存储完成,空间的地址还没有给obj,此时的obj是undefined,obj.n<=>undefined.n
 */
/*
var obj = {
    n: 10,
    m: obj.n * 10 //=>Uncaught TypeError: Cannot read property 'n' of undefined
};
console.log(obj.m);
*/
var obj = {
    n: 10
};
obj.m = obj.n * 10;
console.log(obj.m); //=>100
var ary1 = [3, 4];
var ary2 = ary1;
ary2[0] = 1;
ary2 = [4, 5];
ary2[1] = 2;
ary1[1] = 0;
console.log(ary1, ary2); //[1,0]   [4,2]

posted @ 2019-10-11 18:34  yindanny  阅读(256)  评论(0编辑  收藏  举报