数据类型
基本数据类型:
1.number 数据性 2.string 字符串型 3.boolean 布尔型 4.undefined 未定义 5.null 空引用
引用数据类型:
1.object 对象 2.function 函数 3.array 数组
引用数据类型和值类型(基本数据类型)存储区别:
// 值类型在变量中存放的值本身, 引用数据类型在变量中存的是引用地址 // 变量到变量的赋值 => 将变量里面的内容拷贝一份给到另外一个变量 // 值类型 let a = 10; let b = a; b = 20; console.log(a); // 10 console.log(b); // 20 //引用数据类型 let a = { name: 'zs', age: 18, }; let b = a; b.name = 'ls'; console.log(a.name); // ls console.log(b.name); // ls
基本数据类型
-
Number 数据型
1.所有的数字(不管整数和小数)都是Number数据类型, 多用于计数和数学运算
2.场景: 多用于计数和数学运算
// Number 数据类型 let a = 1; let b = 3.14; let c = 0x11;
-
String 字符串
1.所有添加了引号的数据都是字符串数据类型 单双引号都可
2.场景: 一般用于表示文本数据,描述文案等, 使用的最为广泛的一种数据类型
// String 数据类型 let str1 = '今天天气真不错'; let str2 = '2500'; let str3 = '10086:"亲,天冷了,记得加衣服呀"';
-
boolean 布尔型
1.只有两种可能:true(真) 或者 false(假)
2.场景: 条件的判断
// Boolean数据类型 console.log(true); console.log(false);
-
Undefined 未定义
1.只有一个值,就是它本身. 表示未定义 变量只声明没有赋值的时候浏览器默认会赋值一个undefined
// Undefined 数据类型 let a; console.log(a); // undefined
-
Null 空引用
1.只有一个值 就是它本身 表示空 期待未来这里是一个对象或者还不明确是什么数据类型的时候使用null
// Null 数据类型 console.log(null); let a = null; console.log(typeof null); // object 历史遗留问题
-
基本数据类型转换
将数据转换成Number类型
1.parseInt(需要转换的数据)
2.parseFloat(需要转换的数据)
3.Number(需要转换的数据)
let a = '111'; let b = parseInt(a); let c = parseFloat(a); let d = Number(a); console.log(typeof a, typeof b, typeof c, typeof d); // String Number Number Number // 共同点:都可以转换成Number类型 // 不同点:parseInt => 将数据转换成整数 // parseFloat => 将数据转换成小数 // Number => NaN (not a number) 但凡遇到不能转换的直接返回NaN //使用: 在不明确数据是否能够转换成功的时候,使用Number转换,更加安全, 如果明确数据是什么样子,主要针对数据做一些处理的时候,可以使用parse系列 比如 '100px' 转换成100 ``` 2.将数据转化成String类型 - 变量.toString(); - String(需要转化的数据); ```js let a = 111; let b = a.toString(); let c = String(a); console.log(typeof b, typeof c) // String String // 区别:变量.toString(); null和undefined是用不了 ``` 3.将数据转化成Boolean类型 - Boolean(需要转化的数据) ```js let a = 111; let b = Boolean(a); console.log(b); // true // 注意点:除了 0、''、null、undefined、NaN 这5项转换布尔类型时为false,其它的任意值转换为Boolean类型都为true ``` 4.转换拓展 - 当+号的左边没有数据,只有右边有数据的时候, 这个+号就会被解析成正号,正号后面一定是Number 所以JS引擎自动转换 (隐式转换) - NaN: 任何数字和NaN沾边 结果一定是NaN - 任何数据只需要跟字符串相加最终结果一定是字符串 - [丢失精度](https://segmentfault.com/a/1190000008268668) => 扩大到整数去运算 ```js console.log(0.1 + 0.2); //0.30000000000000004 console.log((0.1 * 100 + 0.2 * 100) / 100); // 0.3 ```
引用数据类型
-
Object 对象
1.何为对象:万物皆对象 客观世界中的具体的实体都是对象
2.创建对象
// 字面量 let obj1 = { name: 'zs', age: 18, }; // 系统内置构造函数 let obj = new Object(); obj.name = 'zs'; obj.age = 18;
3.使用JS对象描述一个人
let qg = { age: 18, name: '张三', girlFriends: ['如花', '乔碧萝殿下'], sing: function () { console.log('男人苦,男人累,男人哭吧哭吧不是罪'); }, rap: function () { console.log('hi 哈 耶~~~~'); }, };
4.JS的对象本质就是一个数据集合 => 增删改查
// 1.对象里面的函数称之为方法 // 2.查语法 => 对象名.属性名 console.log(qg.age) // 18 console.log(qg.girlFriends); // ['如花', '乔碧萝殿下'] console.log(qg.sing); // 函数本身 qg.sing(); // 男人苦,男人累,男人哭吧哭吧不是罪 // 3.改语法 => 对象名.属性名 = 新值 qg.hair = '地中海'; console.log(qg); // 地中海 // 4.增语法 => 对象名.新属性名 = 新值 qg.height = 170; console.log(qg.height); // 170 // 5.删语法 => delete 对象名.属性名 delete qg.girlFriends;
5.工厂函数创建对象
// 需求: 批量创建学生对象 姓名 年龄 地址 ... // 函数功能: 创建学生对象 给这些学生对象添加对应的属性 并且返回学生对象 function createStudent(nameVal, ageVal, addressVal) { // 创建空对象 let student = {}; // 给空对象添加属性 => 增语法 student.name = nameVal; student.age = ageVal; student.address = addressVal; // 返回该对象 return student; } let zs = createStudent('zs', 18, '上海'); let ls = createStudent('ls', 28, '背景'); console.log(zs); // {name:'zs',age:18,adress:'上海'} console.log(ls); // {name:'ls',age:28,adress:'北京'}
6.自定义构造函数创建对象
// 构造函数 => 本质上就是一个普通的函数, 只是我们把配合new调用的函数叫做构造函数, 为了和普通函数做区分, 建议将构造函数的首字母大写 function Student(nameValue, ageValue, address) { // 1. 创建一个新对象 // 2. 将函数里面的this指向了这个新对象 // 3. 执行了这个函数体 => 给这个新对象添加属性 this.name = nameValue; this.age = ageValue; this.address = address; // 4. 返回了这个新对象 } // 创建对象zs let zs = new Student('zs', 18, '铁岭'); // Student{name:'zs',age:18,adress:'铁岭'} // 创建对象ls let ls = new Student('ls', 20, '上海'); // Student{name:'ls',age:20,adress:'上海'} // 相比较工厂函数而言 // 1. 代码量更少 => 不需要手动声明和返回 // 2. 有明确的对象类型 => 类型的名称是构造函数的名称 => 可以实现方法共享 (原型) // new的作用: // new 是一个运算符 => 是一种函数的调用模式 function fn() { console.log('哈哈哈哈'); } fn(); // 普通调用 new fn(); // new 调用 // 不同点 function obj() { console.log(this); console.log('哈哈哈哈'); } let result = obj(); // 普通调用 console.log(result); // undefined let result2 = new obj(); // new 调用 console.log(result2); // obj对象 // new 会悄咪咪的做四件事情 // 1. 会在函数体里面自动创建一个新对象 // 2. 会将函数里面的this指向这个新对象 // 3. 会执行函数体 // 4. 会自动返回这个新对象
7.[]语法操作对象的属性
// 1. 可以使用点语法操作对象的属性 => 对象名.属性名 // 2. 可以使用[]语法实现相同的操作 => 对象名[属性名] // 共同点: 都可以操作对象的属性 let obj = { name: 'zs', age: 18, }; console.log(obj.name); // zs console.log(obj['name']); // zs // 不同点: []可以识别变量(前提[]中的变量不可以加引号) let obj = { name: 'zs', age: 18, temp: '我就是一个搅屎棍', }; l let temp = 'age'; console.log(obj.temp); // 我就是一个搅屎棍 console.log(obj['temp']); // 我就是一个搅屎棍 console.log(obj[temp]); // 18 // 应用场景:遍历对象的时候
8.遍历对象
// 遍历对象: 将对象里面的每个属性都访问一遍 // 专门的语法 => for (let 变量名 in 对象名) {} let obj = { name: 'zs', age: 18, address: '上海', gender: 'male', }; for (let attr in obj) { console.log(attr); // name age address gender console.log(obj[attr]); // zs 18 上海 male }
-
Function 函数
1.JS的函数是为了复用,函数本身是不会主动执行的,必须调用之后才会执行
2.函数一次声明, 可以多次调用, 每一次调用本质上就是将函数里面的代码重新执行一次
3.语法
// JS的函数的语法 // 1. 声明函数: function 自定义的函数名 (){ // 代码块 } // 2. 调用函数: 自定义的函数名(); // 函数是不会主动执行的 function greet() { // 函数体 console.log('hellow world!'); } // 调用 => 将函数体里面的代码执行一遍 greet(); // hellow world! greet(); // hellow world!
4.函数传参
// 声明函数: function 函数名(形参1, 形参2, ...){} // 调用函数: 函数名(实参1, 实参2, ...); // 需求: 根据不同的人打招呼 function greet(person, content) { console.log(person +','+ content); } greet('张三', '早上好'); // 张三,早上好 greet('李四', '晚上好'); // 李四,晚上好 // 小结 // 什么时候传参: 在复用的时候,有些数据会根据使用的情况不同而不同,这个时候就需要将这个数据提取出来作为参数传递 // 提取学术名词 // 形式参数: 函数声明小括号里面的变量 简称形参 // 实际参数: 函数调用小括号里面的内容 简称实参 // 实参传递给形参的过程 称之为传参 (赋值) // 参数和参数之间使用逗号进行隔开
5.函数的返回值
// 1.函数内部return后面的内容就是函数的返回值 // 2.内置函数中, 有的函数有返回值 有的没有返回值 // 3.函数的返回值可以是任意类型 // 4.当一个函数有返回值的时候,函数调用后的结果就是这个返回值,可以用变量接收 // 需求: 调用两次求和函数,得到每一次的结果,比较这两个结果的大小 function getSum(a, b) { let sum = a + b; return sum; // 函数的返回值 } let sum1 = getSum(10, 20); let sum2 = getSum(5, 16); console.log(sum1); // 30 console.log(sum2); // 21
6.函数的内部可以调用函数
// 函数内部可以调用函数 => 可以将一个复杂的需求拆解成多个小需求, 每一个函数负责完成一个小需求,最终可以将每一个小需求的结果得到最终完成大需求 // 1. 求任意数的阶乘 => 5! = 5 * 4 * 3 * 2 * 1 function getJc(n) { // 注意点: 累乘的初始值必须是1 不能是0 因为0乘任何数得0 let result = 1; for (let i = 1; i <= n; i++) { result *= i; } return result; } console.log(getJc(5)); // 120 console.log(getJc(4)); // 24 // 2. 求阶乘的和 => 2-4的阶乘和 function getSum(m, n) { let sum = 0; for (let i = m; i <= n; i++) { // i => 2,3,4 // getJc(i) => 2!,3!,4! sum += getJc(i); } return sum; } console.log(getSum(1, 3)); // 288
7.函数的补充
// 两个相同的函数后面的会覆盖前面的函数 function fn() { console.log('哈哈'); } function fn() { console.log('嘻嘻'); } fn(); // 嘻嘻 // 在Javascript中 实参的个数和形参的个数可以不一样 // 如果实参过多 那么多余的实参会被忽略 (函数内部有一个arguments,里面装着所有的实参) // arguments => 函数里面的一个关键字 => 实参列表 => 用于参数的个数不确定的情况的 // 如果形参过多 会自动填上undefined // 形参过多 function test(a, b, c, d) { console.log(a, b, c, d); // 10 undefined undefined undefined undefined .. } test(10); // 实参过多 function test(a) { // 实参列表 => 函数内部拥有的一个关键字 => 将所有的实参存储在里面 console.log(arguments); // [10, 20, 30, 40] console.log(a); // 10 } test(10, 20, 30, 40); // push可以传递多个参数 let arr = []; arr.push(1, 2, 3); console.log(arr); // [1, 2, 3] // 函数一遇到return就会跳出函数 不会在继续往下执行了 // 函数的跳出用return 循环的跳出用break 函数里面的循环可以使用return跳出 // 所以,return是没有办法返回两个结果出来的, 如果需要返回多个值 返回一个数组 function test() { console.log('return之前'); return [1111, 2222]; console.log('return之后'); } console.log(test()); // return之前 && [1111, 2222]
8.作用域
// 作用域:变量起作用的区域 // 全局作用域: 函数外面的区域 // 函数作用域(局部作用域): 函数内部的区域 // 全局变量: 在函数外部let 的变量 => 全局变量在任何区域都可以访问和修改 // 局部变量: 在函数内部let 的变量 => 局部变量只能在当前函数内部访问和修改 // 全局作用域 // 全局变量 let a = 10; function fn() { // 函数作用域 // 局部变量 let b = 20; // 全局变量 a = 30; // 把30赋值给全局变量的a console.log(a); // 30 console.log(b); // 20 } fn(); console.log(a); // 30 console.log(b); // 报错 b is not defined // 变量的访问原则: 在能够访问到的情况下 先局部 后全局 let a = 10; // 全局变量 // let a = 20; // 报错 function fn() { let a = 20; // 局部变量 console.log(a); // 20 } fn(); console.log(a); // 10
9.预解析(了解)
// 预解析: 在JS逐行运行之前 ,将变量声明和函数声明提前 (赋值不提升) // 提前: 放到当前作用域的做前面 // 变量 console.log(a); // undefined var a = 10; // 上面可以理解为 // var a; // console.log(a); // undefined // a = 10; // 函数 fn(); function fn() { console.log('哈哈哈哈'); } // 上面可以理解为 function fn() { console.log('哈哈哈哈'); } fn(); // 如果遇到同名的函数和变量,函数优先(权重更高)。 // 预解析之后 将函数声明提前 两个同名的函数覆盖
10.匿名函数
// 匿名函数:顾名思义,没有名字的函数 // 语法:function () {} // 应用方式: // 1. 函数表达式 // 2. 匿名函数自执行 // 函数表达式:将函数赋值给一个变量 let a = function () { console.log('hello world!'); } a(); // 直接调用 // 匿名函数自执行 => 沙箱模式 // 匿名函数自执行不能用来复用,而是用来提供作用域的 (function () { console.log('hello world!'); })() // 场景演示 // 张三 (function () { function fn() { console.log('这是我三哥的代码 功能及其牛叉'); } fn(); })(); // 李四 (function () { function fn() { console.log('这是我四哥的代码, 功能相当强大'); } fn(); })(); ``` 11. 函数也是一种类型 ```js // 1.函数可以赋值给一个变量 => 函数表达式 // 通常是一个匿名函数 let a = function () { console.log('hello world!'); } a(); // hello world! // 2.函数可以作为参数 function fn(n) { n(); // 我是回调函数 } fn(function () { console.log('我是回调函数') }) // 3.函数可以作为返回值 function fn() { return function() { console.log('我是被返回出来的函数'); } } let a = fn(); // function() { console.log('我是被返回出来的函数'); } a(); // 我是被返回出来的函数 ```
-
Array 数组
1.概念:所谓数组,就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合我们就称之为数组
2.数组的特点
- 数组使用 [] 表示 数据和数据使用逗号隔开
- 数组都有下标,下标默认都是从0开始 然后逐次+1
- 数组中有length属性,它会自动随着数组长度的变化而改变
3.创建数组
-
字面量的形式创建数组(推荐使用)
let arr = ['张三', '李四', '王五']; console.log(arr); // ['张三', '李四', '王五']
-
系统内置构造函数(了解)
let arr = new Array(); console.log(arr); // []
4.数组的使用
-
数组 => 数据的集合 => 但凡是数据的集合: 增,删,改,查
let arr = ['乔碧萝殿下', '凤姐', '迪丽热巴']; // 查 => 数组名[下标] console.log(arr); // ["乔碧萝殿下", "凤姐", "迪丽热巴"] console.log(arr[0]); // 乔碧萝殿下 console.log(arr[1]); // 凤姐 console.log(arr[2]); // 迪丽热巴 // 改 => 数组名[下标] = 新值 arr[0] = '芙蓉姐姐'; arr[1] = '马保国'; console.log(arr); // ["芙蓉姐姐", "马保国", "迪丽热巴"] // 删 => 数组名.splice(操作的下标, 删除的个数) arr.splice(0, 1); console.log(arr); // ["马保国", "迪丽热巴"] // 增 => 数组名[数组名.length] = 值 // length属性代表数组的长度, 从1开始计算 永远比当前的最大下标大 1 // length属性是JS自动维护的 // 获取length属性 => 数组名.length arr[arr.length] = '西施'; arr[arr.length] = '貂蝉'; console.log(arr); // ["马保国", "迪丽热巴", "西施", "貂蝉"] // 数组中提供了内置对象的语法 .push(添加的数据) arr.push('大乔'); console.log(arr); // ["马保国", "迪丽热巴", "西施", "貂蝉", "大乔"]
5.遍历数组
-
公式: for (let i = 0; i < arr.length; i++) { }
-
arr[i] 就代表着数组的每一项
let arr = ['乔碧萝殿下', '凤姐', '迪丽热巴']; for (let index = 0; index < array.length; index++) { console.log(array[index]); } //提醒: 在for循环遍历数组中,不要轻易使用splice删除元素,因为这样会导致数组的长度发生改变,并且对应的下标混乱
typeof
typeof 数据 => 可以返回这个数据的数据类型 针对简单数据有效
let a = 12; let b = 'abc'; console.log(typeof a); // Number console.log(typeof b); // String
数据类型的转换
-
转换成number
1.parseInt() => 把字符串转换成整数, 遇到小数点或不能转换的则停止,将前面转换好的输出
2.parseFloat() => 把字符串转换成小数, 遇到不能转换的停止,将前面转换好的输出
3.Number() => 在转换的过程中,只要遇到有不能转换的直接输出成NaN
4.NaN: is not a number (不是一个有效的数字) 不是数据类型,是Number类型的一个特殊值使用: 在不明确数据是否能够转换成功的时候,使用Number转换,更加安全, 如果明确数据是什么样子,主要针对数据做一些处理的时候,可以使用parse系列 比如 ‘100px’ 转换成100
-
转换成字符串
1.变量.toString() 将数据转换成字符串
2.String() 将数据转换成字符串
注意:有些数据不能用toString 比如 undefined null
-
转换成布尔类型
1.使用 boolean() 转换
2.除了 0、null、undefined、NaN 这四个是false ,其余全为true