引用数据类型
数据类型的区别
存储的区别
- 基本数据类型:存储在
栈内存中 - 引用数据类型:将数据本体存在
堆内存中,变量名存储在栈内存中,变量名内部存储着指向堆内存的地址
赋值的区别
- 基本数据类型:将变量中的
数据赋值给另一个变量,赋值后二者毫无关系 - 引用数据类型:将变量中的
地址赋值给另一个变量,赋值后二者同一个地址指向同一个数据
比较的区别
- 基本数据类型:进行
值的比较 - 引用数据类型:进行
地址的比较
传参的区别
- 基本数据类型:将变量内部的
数据复制一份, 传递给对应的形参, 所以函数内对这个形参的修改不会影响外界 - 引用数据类型:将变量内部的
地址复制一份, 传给对应的形参, 所以此时函数内形参和变量的内部存储的是同一个地址,所以在函数内部对这个形参的一些修改,会影响外界
函数
- 概念:存放需要重复多次的代码,随拿随取
函数的定义与调用
- 1.定义
- 声明式:function 函数名(){}
- 在函数定义前或者后都可以调用函数
- 赋值式:var 函数名 = function () {}
- 在函数定义后可以调用, 函数定义前不能调用, 因为此时变量内部的值为 undefined
- 声明式:function 函数名(){}
- 2.调用
- 函数名(实参/或者不传和
function box() {
console.log(1 + 1)
}
// 2. 函数调用
box()
变量和函数的预解析
变量
- 变量提升
JS 在运行我们的代码的时候, 会先整体阅读一次我们的代码,读取完毕后, 会将变量的声明(定义)提取到页面的最顶部(JS代码的最顶部)
**注意: 提升的只有变量的声明, 没有变量的赋值** - 在变量定义前去使用, 得到的是一个 undefined
函数的参数
- 目的:使函数功能更加灵活
- 1.形参:函数定义时括号内容,具体的值由实参传递,为传递则为undefined
- 2.实参:调用时括号内容,将值传递给对应的形参
- 函数中参数可以有默认值(ES6中新写法)
函数的返回值
- 概念:每一个函数调用完毕后,都会有一个返回值,每一个函数中, 默认具有一个 return, 在函数内部的最后一行, 默认为 return undefined
- 需要在函数的内部手动书写一个返回值;return 你需要返回的内容
- 功能:
- 具有中断函数的能力,不执行之后的语句
- 将函数内部的一些值, 返回给函数外部, 让函数外部可以使用
//判断质数
function fn(n) {
var num = 0;
for (var i = 2; i < n; i++) {
if (n % i === 0) {
num++
}
}
return num === 0
}
var a = prompt()-0
var res = fn(a)
console.log(res)
作用域
- 变量生效的范围
全局作用域
- 整个 script 标签内部的区域声明的变量就是在
全局作用域创建 - 在全局作用域创建的变量或者函数我们统称为==>全局变量或者全局函数
- 能在当前代码的所有位置去使用
局部作用域(函数作用域)
- 在一个函数内部生成的变量就是存在于
局部作用域 - 在局部作用域创建的变量只能在当前作用域内使用
作用域链
- 每一个作用域上一层会有一个全新的作用域, 每个作用域之间的一个连接, 我们称之为
作用域链
规则
查找规则
- 在一个作用域内查找一个变量, 如果有直接使用, 如果没有会去上一层继续查找
- 如果找到直接使用, 没有的话继续去上一层查找直到找到了全局作用域, 找到了直接使用, 如果没有找到直接报错
注意: 查找的时候只会层层向上, 不会向下
赋值规则
- 在一个作用域对一个变量进行赋值, 那么会先在当前作用域内查找变量, 找到直接修改, 如果没有, 会去上一层作用域查找
- 如果找到直接修改, 没有继续向上, 如果找到了全局作用域还是没有, 那么会在全局作用域创建一个变量, 然后对他进行赋值操作
递归
- 含义:递归函数就是在一个
函数内部调用自身. 循环执行 - 递归函数有点类似于循环
- 需要有初始化, 自增, 执行的代码, 判断条件
- 如果上述的内容缺少, 那么就是一个死递归, 永远不会结束
对象
- 1.键值对 2.key/value 3.属性名:属性值
对象的操作
创建
字面量构造
var obj1 = {} console.log(obj1)
内置构造函数
var obj2 = new Object() console.log(obj2)
操作
-
增
- 点语法:对象名.新的属性名 = 对应的属性值 :
obj.age = 18 - 中括号语法:对象名['要新增的属性名'] = 对应的属性值 :
obj['age'] = 18
- 点语法:对象名.新的属性名 = 对应的属性值 :
-
删
- 点语法:delete 对象名.要删除的属性名 :
delete obj.id - 中括号语法:delete 对象名['要删除的属性名'] :
delete obj['id']
- 点语法:delete 对象名.要删除的属性名 :
-
改
- 点语法:对象名.要修改属性值的属性名 = 新的属性值 :
obj.name = 'Mary' - 中括号语法:对象名['要修改的属性名'] = 新的属性值 :
obj['name'] = 'Lisa'
- 点语法:对象名.要修改属性值的属性名 = 新的属性值 :
-
查
- 点语法:对象名.要查询的属性名 :
console.log(obj.name) - 中括号语法:对象名['要查询的属性名'] :
console.log(obj['name'])
- 点语法:对象名.要查询的属性名 :
对象的遍历
let obj = {
name: '张三',
id: 'QF001',
a:100,
age:15
}
for(let key in obj){
console.log(obj[key]);
}
数组
创建
- 数组内部数据可以不一致,但是一致的数据会方便后续的批量操作
字面量构造
var arr1 = {} console.log(arr1)<==使用场景较多
内置构造函数
ar arr2 = new Array() console.log(arr2)var arr2 = new Array(10) console.log(arr2)<==创建有长度的数组var arr2 = new Array(10) console.log(arr2)<==创建有内容的数组
长度:length
- 数组的长度取决于内部有多少元素
- 下标
- 从0开始
常用算法
冒泡排序
var a = [20, 17, 16, 4, 9, 3, 7];
for (var i = 0; i < a.length - 1; i++) {
for (var j = 0; j < a.length - 1 - i; j++) {
if (a[j] > a[j + 1]) {
var temp = a[j];
a[j] = a[j + 1];
a[j + 1] = temp;
}
}
}
选择排序
var a = [20, 17, 16, 4, 9, 3, 7];
for (var i = 0; i < a.length - 1; i++) {
var min = i;
for (var j = i + 1; j < a.length; j++) {
if (a[j] < a[min])
min = j;
}
var temp = a[i];
a[i] = a[min];
a[min] = temp;
}
console.log(a);
数组方法
1.push()
- 语法:数组. push()
- 作用:在数组后面追加元素
- 返回值:数组长度
console.log(arr.push(9));
console.log(arr)
//函数
function push(a, num) {
a[a.length] = num;
return a.length;
}
console.log(push(arr, 'we'));
console.log(arr)
2.pop()
- 语法:数组. pop()
- 作用:在数组后面删除元素
- 返回值:返回删除的元素
console.log(arr.pop());
console.log(arr)
// 函数
function pop(a) {
var temp = a[a.length - 1]
//删除后值没了 长度不变
delete a[a.length - 1]
//位置变了 值变了
a.length -= 1
return temp;
}
console.log(pop(arr))
3.unshift()
- 语法:数组. unshift()
- 作用:在数组前面追加元素
- 返回值:返回数组长度
console.log(arr.unshift(2));
console.log(arr)
// 函数
var a1 = [1, 2, 3]
function unshift(a, data) {
// 一个新的数组来存值
var b = [data];
for (var i = 0; i < a.length; i++) {
b[i + 1] = a[i]
}
return {
arr: b,
len: b.length
}
}
var r = unshift(a1, 'xixi')
console.log(r)
4.shift()
- 语法:数组. shift()
- 作用:在数组前面删除元素
- 返回值:返回删除的元素
var a2 = [ 1, 2, 3]
console.log(a2.shift());
function shift(a) {
var temp = a[0]
for (var i = 0; i <= a.length - 1; i++)
a[i] = a[i + 1]
a.length -= 1
return temp
}
var r2 = shift(a2)
console.log(r2)
5.reverse()
- 将数组进行反转
- 返回值:反转后的数组 会改变原数组
var arr3 = [1,2,3,4,5,6]
console.log(arr3.reverse())
function reverse(a) {
// 从头开始 到中间停止 前后交换
for (var i = 0; i < a.length / 2; i++) {
var temp = a[i]
a[i] = a[a.length - 1 - i]
a[a.length - 1 - i] = temp
}
return a
}
var r1 = reverse(arr3)
console.log(r1)
6.sort() 排序 // 开发的时候,没有特别要求使用sort // 面试的时候不要一开始说sort
- 语法一:数组名.sort()
- 作用:将数组内的数据,转换为字符串,然后一位一位对比
- 语法二:
数组名.sort(function (a,b) { return a- b}) - 作用:按照数字从小到大
- 语法三:
数组名.sort(function (a,b) { return b - a}) - 作用:按照数字从大到小返回值:返回一个排序好的数组
var arr4 = [12, 20, 30, 40, 50, 100]
console.log(arr4.sort())
var so = arr4.sort(function (a,b) { return b - a})
console.log(so);
7.indexOf()
- 数组.indexOf(数据,从哪个下标开始()第二个参数不传,默认为0)
- 作用:从左到右的顺序,查找数组中是否包含这个数据 返回值:找到:返回从左到右第一次出现的下标 否则返回-1
var a = [1, 2, 3, 4, 5, 6,1]
console.log(a.indexOf(2));
console.log(a.indexOf(7));
console.log(a.indexOf(5, 1));
console.log(a.indexOf(2, 7));
function indexOf(a, data, index = 0) {
for (var i = index; i < a.length; i++) {
if (a[i] === data)
return i
}
return -1
}
console.log(indexOf(a, 5,2))//4
console.log(indexOf(a, 1,2))//6
console.log(indexOf(a, 2,2))//-1
8.splice() 剪切 or 删除
- 语法一 数组.splice(开始下标数,剪切数量)
var arr = [1,2,3,4,5]
var res = arr.splice(1, 3)
console.log('剪切到'+res);
- 语法二:数组.splice(开始下标数,剪切数量,数据一,数据二,数据三...)
- 返回值:剪切到的内容
var arr2 = ['jizhixing', 'guoenhui', 'wozuimei']
var res1 = arr2.splice(1, 1, 'dameinv', 'pianrende')//添加的
console.log(arr2)
console.log(res1)//返回删除的
arr2.splice(0, 0, 'qwertrytu')
console.log(arr2)
arr2.splice(5, 0, 'qasadfdgfd')
console.log(arr2)
9.slice()
- 语法:`数组名.slice('开始下标','结束下标')`
- 作用:将选中的数据复制(包含开始下标不包含结束下标)
- 返回值:以数组形式返回复制的内容
var arr = [1,2,3,4,5,6,7,8,9,10]
var res = arr.slice(0,3)
console.log(res); //[1, 2, 3]
10.concat()
- 语法:数组.concat(其他数组)
- 作用:将其他数组和数组拼接在一起
- 返回值:拼接好的新数组
var arr = [100, 200, 300, 400, 100, 500]
var res = arr.concat([500, 600])
console.log(arr, res)//[100, 200, 300, 400, 100, 500] [100, 200, 300, 400, 100, 500, 500, 600]
var arr2 = ['hello', 'world']
var res2 = arr.concat(arr2)
console.log(arr, res2)//[100, 200, 300, 400, 100, 500] [100, 200, 300, 400, 100, 500, 'hello', 'world']
11.join()
- 语法:数组.join()
- 作用:将数组用 连接符 连接成为一个字符串
- 返回值:连接好的字符串
var arr = [100, 200, 300, 400, 100, 500]
var res = arr.join('---')
console.log(arr, res)//[100, 200, 300, 400, 100, 500] '100 & 200 & 300 & 400 & 100 & 500'
12.lastIndexOf()
- 语法:数组.lastIndexOf(数据)
- 作用:从右向左查找数据在数组中的索引位置
- 返回值:有该数据,返回第一次出现的索引位置 没有该数据,返回-1
var arr = [100, 200, 300, 400, 100, 500]
var res=arr.indexOf(100)
console.log(res)//0
var res2=arr.lastIndexOf(100)
console.log(res2)//4
13.forEach() ==> 遍历数组使用
- 语法:数组.forEach( function ( item, index, arr ) {} )
- item:数组中每一个元素
- index:每一个元素对应的下标
- origin:原数组 (很少用)
- 作用:遍历数组
- 返回值:无
var arr = [100, 200, 300, 400, 100, 500]
arr.forEach(function (item, index, arr) {
console.log(item)
console.log(index)
console.log(arr)
console.log('--------------')
})
14.map()
- 语法:数组.map(function (item, index, arr) { })
- 作用:根据原数组映射一个新数组
- 返回值:映射后的新数组(需要在函数内部书写return)
var arr = [100, 200, 300, 400, 100, 500]
var res = arr.map(function (item, arr) {
return item * 10
})
console.log(arr, res) //[100, 200, 300, 400, 100, 500] [1000, 2000, 3000, 4000, 1000, 5000]
forEach()和map()语义不同
15.filter()
- 语法:数组.filter(function (item, index, arr) { }
- 作用:过滤数组
- 返回值:过滤后的新数组
var arr = [100, 200, 300, 400, 100, 500]
var res = arr.filter(function (item, index, arr) { return item > 100 })
console.log(res)//[200, 300, 400, 500]
var res2 = arr.filter(function (item, index, arr) {
return index > 3
})
console.log(res2)// [100,500]
16.every()
- 语法:数组.every(function (item, index, arr) { })
- 作用:判断数组是不是每一项都满足条件
- 返回值:一个布尔
var arr = [100, 200, 300, 400, 100, 500]
var res = arr.every(function (item, index, arr){
return item > 5
})
console.log(res)//true
17.some()
- 语法:数组.some(function (item, index, arr) {})
- 作用:判断数组是不是某一项满足条件
- 返回值:一个布尔
var arr = [100, 200, 300, 400, 100, 500]
var res = arr.some(function (item, index, arr) {
return item > 150
})
console.log(res)//true
18.reduce()叠加后的效果
- 语法: 数组.reduce(function (prev, item, index, origin) {}, init)
- prev: 如果是第一次执行那么可能是 数组[0] 的值, 也有可能是 init 的值,如果是第一次后续的执行, 那么他的值就是上一次遍历返回的结果
- item: 这个表示的是数组中的每一项
- index: 这个表示的是每一项对应的索引 // arr: 这个表示的是原数组
- init:随意传递一个值即可, 只要符合需求
- 作用: 就是用来叠加的
- 返回值: 就是叠加后的结果
- 注意: 以return的形式书写返回条件
var arr = [1, 2, 3, 4, 5]
var res = arr.reduce(function (prev, item) {
return prev *= item
}, 2)
console.log(res);//240=2(初始值)*1*2*3*4*5
19.find()用来获取数组中满足条件的第一个数据
- 语法: 数组名.find(function (item, index, arr) { })
- item: 这个表示的是数组中的每一项
- index: 这个表示的是每一项对应的索引
- arr: 这个表示的是原数组
- 作用: 用来获取数组中满足条件的数据
- 返回值: 如果有 就是满足条件的第一个数据;如果没有就是undefined
- 注意: 要以return的形式执行返回条件
var arr = [1, 2, 3, 4, 5]
console.log('原始数组 : ', arr);
var res = arr.find(function (item) {
return item > 3
})
console.log(res)//4
20.findIndex()用来获取数组中满足条件的第一个数据的下标
- 语法: 数组名.findIndex(function (item, index, arr) { })
- item: 这个表示的是数组中的每一项
- index: 这个表示的是每一项对应的索引
- arr: 这个表示的是原数组
- 作用: 用来获取数组中满足条件的数据
- 返回值: 如果有 就是满足条件的第一个数据下标;如果没有就是-1
- 注意: 要以return的形式执行返回条件
var arr = [1, 2, 3, 4, 5]
console.log('原始数组 : ', arr);
var res = arr.find(function (item) {
return item > 3
})
console.log(res)//4