编程语言
首页 > 编程语言> > 在拉钩学习的笔记(六)JavaScript数组、对象、函数

在拉钩学习的笔记(六)JavaScript数组、对象、函数

作者:互联网

1、数组
    之前学习的数据类型,只能存储一个值(比如:Number/String)。如果我们想存储多个数值该如何存储
    概念: 所谓数组(Array),就是将多个元素(通常是一类型)按一定顺序排列放到一个集合中,那么这个集合我们就称之数组。
    定义:数组是一组有序的数据集合。数组内部可以存放多个数据,不限制数据类型,并且数组的长度可以动态调整。
    创建数组最简单的方式就是数组字面量方式
    数组的字面量:[]
    一般将数组字面量赋值给一个变量,方便后期对数组进行操作。
    如果存放多个数据,每个数据之间用逗号分隔,最后一个后面不需要加逗号
2、获取数组元素
    数组可以通过一个index(索引值、下标)去获取对应的某一项数据,进行下一步操作
    index:从0开始,按照整数排序往后排序,例如:0,1,2,3……
    可以通过index获取某一项值之后,使用或者更改数组项的值
    调整数据:利用数组变量名后面直接加[index]方式
    注意:如果索引值超过了数组最大项,相当于这一项没有赋值,内部存储的就是undefined;
    更改数据:arr[index]调用这一项数据,后面等号赋值更改数据
3、数组的长度
    数组有一个length属性,记录的是数组的数据的总长度
    使用方法:变量名.length     console.log(arr.length)
    数组的长度与数组最后一项的下标存在关系,最后一项的下标等于数组的length-1
    获取最后一项数据时,可以这样写: console.log(arr[arr.length-1]);
    数组的长度不是固定不变的,可以发生更改
    增加数组的长度:直接给数组length属性赋一个大于原来长度的值。赋值方式用等号赋值
        或者可以给一个大于最大下标的项直接赋值,也可以强制拉长数值
    缩短数组长度:强制给length属性赋值,后面的数据会被删除,删除是不可逆的
4、数组遍历
    遍历:遍及所有,对数组的每一个元素都访问一次就叫遍历。利用for循环,将数组中的每一项单独拿出来,进行一些操作。
    根据下标0 到arr.length-1之间,进行for循环遍历

1、对象的概念
    为什么要有对象:如果由一组相关的数据,松散的存储不利于使用,存入数组中受下标限制又必须有固定的顺序,而对象可以自定义名称存储一些列无序的相关顺序
    什么是对象:万物皆对象,对象是一个具体的事物,一个具体的事物就会有行为和特征
    JavaScript中的对象是无序属性的集合
    其属性可以包含基本值、对象或函数。对象就是一组没有顺序的值。我们可以把JavaScript中的对象想象成键值对,其中值可以是数据和函数
    对象的行为和特征:
        特征---在对象中用属性表示
        行为---在对象中用方法表示
2、对象字面量
    创建一个对象最简单的方式是使用对象字面量赋值个变量。类似数组
    对象字面量语法:{}
    内部可以存放多条数据,数据与数据之间用逗号分隔,最后一个后面不用加逗号
    每条数据都是有属性名和属性值组成,键值对写法: k:v
    k:属性名
    v:属性值,可以是任意类型的数据,比如简单类型数据、函数、对象
    语法:
        var obj = {
            k:v,
            k:v,
            k:v
        };
    区分属性和方法
    属性:对象的描述性特征,一般是名词,相当于定义在对象内部的变量;
    方法:对象的行为和功能,一般是动词,定义在对象中的函数
3、对象数据的调用和更改
    用对象的变量名打点调用某个属性名,得到属性值
    在对象内部用this打点调用属性名。。this替代对象
    用对象的变量名后面加[]调用,[]内部是字符串格式的属性名
    调用方法时,需要在方法名后加()执行
    更改对象内部属性和方法的语法
        更改属性的属性值方法:先调用属性,再等号赋值
        增加新的属性和属性值:使用点语法或者()或者[]方法直接定义新属性,等号赋值
        删除一条属性,使用一个个delete关键字,空格后面加属性调用
4、new Object()创建对象
    Object()构造函数,是一种特殊的函数,主要用来创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中
    构造函数用于创建一类对象,首字母要大写
    构造函数要和new一起使用才有意义
    new在执行时会做的4件事
        new会在内存中创建一个新的空对象
        new会让this指向这个新对象
        执行构造函数 目的:给这个新对象加属性和方式
        new会返回这个新对象
5、工厂函数创建对象
    如果要创建多个类似的对象,可以将new Object()过程封装到一个函数中,将来调用函数就能创建一个对象,相当于一个生产对象的函数工厂,用来简化代码
6、自定义构造函数
    比工厂方法更简单
    自定义一个创建具体对象的构造函数,函数内部不需要new一个构造函数的过程,直接使用this代替对象进行属性和方法的书写,也不需要一个return返回值
    使用时,利用new关键字调用自定义的构造函数即可
    注意:构造函数的函数名首字母需要大写,区别于其他普通函数名
7、对象遍历
    for in 循环也是循环的一种,专门用来遍历对象,内部会定义一个k 变量,k 变量每次在循环时会从第一个开始接收属性名,一直接收到最后一条属性名,执行完后跳出循环
    简单的循环遍历:输出每一项的属性名和属性值
    for (var k = in obj) {
        console.log(K + "项的属性值是" + obj[k]);
    }
8、简单类型和复杂类型的区别
    基本类型又叫做值类型,复杂类型又叫做引用类型
    值类型:简单数据类型,基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型
    引用类型:复杂数据类型,在存储时,变量中存储的仅仅是地址(引用),因此叫做引用数据类型
    堆和栈:JavaScript中没有堆和栈的概念,简单数据类型存储于栈中,复杂类型函数对象存储于堆中
    堆栈空间分配区别:
        1、栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等
        2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收制度回收
9、基本类型在内存中的存储
    变量中如果存储的是简单类型的数据,那么变量中存储的是值本身,如果将变量赋值给另一个变量,是将内部的值复制了一份给了另一个变量,两个变量之间没有联系,一个变化,另一个不会同时变化
10、复杂类型在内存中的存储
    如果将复杂类型的数据赋值给一个变量,复杂类型的数据会在内存中创建一个原型,而变量中存储的是指向对象的一个地址,如果将变量赋值给另一个变量,相当于将地址复制一份给了新的变量,两个变量的地址相同,指向的是同一个类型,不论通过哪个地址更改了原型,都是在原型上发生的更改,两个变量下次访问时,都会发生变化
11、内置对象
    JavaScript包含:ECMAscript DOM BOM
    ECMAscript包含:变量、数据、运算符、条件分支语句、循环语句、函数、数组、对象……
    JavaScript的对象包含三种:自定义对象 内置对象 浏览器对象
    ECMAscript的对象:自定义对象 内置对象
    使用一个内置对象,只需要知道对象中有哪些成员,有什么功能,直接使用
    需要参考一些说明手册W3C/MDN
12、MDN使用方法
    Mozila 开发者网络(MDN)提供有关开放网络技术(open web)的信息,包括HTML、CSS和万维网及HTML5应用的ApI
    MDN:https://developer.mozilla.org/zh-CN/
    比如:通过查询MDN学习Math对象的random()方法的使用
    如何学习一个方法:1、方法的功能;2、参数的意义和类型;3、返回值的意义和类型;4、demo进行测试
13、Math对象
    Math对象它具有数学常数和函数的属性和方法,我们可以直接进行使用
    根据数学相关的运算来找Math中的成员(求绝对值,取整)
    常用Math对象的方法
        Math.PI                         圆周率
        Math.random()                   生成随机数
        Math.floor()/Math.ceil()        向下取整/向上取整
        Math.round()                    取整,四舍五入
        Math.abs()                      绝对值
        Math.max()/Math.min()           求最大和最小值
        Math.sin()/Math.cos()           正弦/余弦
        Math.pow()/Math.sqrt()        求指数次幂/求平方根
14、创建数组对象的两种方式
    字面量方式var arr = []      构造函数方法var arr = new Array()
    检测数组类型    instanceof 检测某个实例是否是某个对象类型返回true或false       (typeof()返回具体类型)
15、数组对象
    toStrint()          把数组转换为字符串,逗号分隔每一项
    数组的常用方法
        首尾数据操作
    push()              在数组末尾添加一个或多个元素,并返回数组操作后的长度
    pop()               删除数组最后一项,返回删除项
    shift()             删除数组第一项,返回删除项
    unshift()           在数组开头添加一个或多个元素,并返回数组的新长度
        合并和拆分:
    concat()            将两个数组合并成一个新的数组,原数组不受影响。参数位置可以是一个数组字面量、数组变量、零散的值
    slice(start,end)    从当前数组中截取一个新的数组,不影响原来的数组,返回一个新的数组,包含从start到end(不包含该元素)的元素。
                        参数区分正负,正值表示下标位置,负值表示从后面往前数第几个位置,参数可以只传递一个,表示从开始位置截取到字符串结尾
        删除、插入、替换
    splice(index,howmany,element1,element2) 用于插入、删除或替换数组的元素
                        index:删除元素的开始位置;howmany:删除元素的个数,可以是0;element1,element2:要替换的新的数据;返回删除值
        位置方法:
    indexOf()           查找数据在数组中最先出现的下标
    lastIndexOf()       查找数据在数组中最后一次出现的下标
                        注意:如果没有找到返回-1
        倒序:
    reverse()           将数组完全颠倒,第一项变成最后一项,最后一项变成第一项
        排序:
    sort()              默认根据字符编码顺序,从小到大排列;如果想要根据数值大小进行排序,必须添加sort的比较函数参数
                        该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数a和b,根据a和b的关系作为判断条件,返回值根据条件分为三个分支,正数、负数、0:
                            返回值是整数1:a排在b后面
                            返回值是负数-1:a排在b前面
                            返回值是0:a和b的顺序保持不变
                        认为能控制的是判断条件
                        arr.sort(function fun(a, b){
                            if(a > b){
                                return 1;
                            } else if (a < b) {
                                return -1;
                            } else {
                                return 0;
                            }
                        })
        转字符串方法:将数组的所有元素连接到一个字符串中
    join()              通过参数作为连字符将数组中的每一项用连字符连城一个完整的字符
    清空数组
        1、arr = [];推荐
        2、arr.length = 0;
        3、arr.splice(0, arr.length);
16、基本包装类型
    为了方便操作简单数据类型,JavaScript还提供了特殊的简单类型对象:String基本类型是没有方法的
    当调用str.substring()等方法的时候,先把str包装成String类型的临时对象,再调用substring方法,最后销毁临时对象
17、字符串的特点
    字符串是不可变的
    由于字符串的不可变,在大量拼接字符串的时候会有效率问题
    字符串对象的常用方法:字符串所有的方法都不会修改字符串本身(字符串是不可变的),操作完成后会返回一个新的字符串
18、字符串方法
    字符串属性
        长度属性:str.length 字符串长度指的是一个字符串中所有的字符总数
    字符串方法
        charAt()            方法可返回指定位置的字符。char:charator,字符;at:在哪;参数是index字符串的下标也是从0开始;表示返回指定下标位置的字符
        indexOf()           方法可返回某个指定的字符值在字符串中首次出现的位置;没有返回值是-1
        concat()            方法用于连接两个或多个字符串。参数比较灵活,可以是字符串、或者字符串变量、多个字符串。生成的是一个新的字符串
        split()             方法用于把一个字符串分割成字符串数组。参数部分是分割符,利用分割符将字符串分割成多个部分,多个部分作为数组的每一项组成数组,如果分割符是空字符串,相当于将每个字符拆分成数组中的每一项
        toLowerCase()       把字符串转换为小写
        toUpperCase()       把字符串转换为大写
            将所有英文符转为大写或者小写;生成的是新的字符串,原字符串不会发生变化
        slice()             方法可以提取字符串的某个部分,并以新的字符串返回被提取部分  slice(start,end)
        substr()            方法可在字符串中抽取从start下标开始的指定数目的字符;substr(start,howmany),howmany参数必须为正数,也可以不写
        substring()         方法用于提取字符串中介于两个指定下标之间的字符;substring(start,end)参数只能为正数,小的是开始位置,大的是结束位置不包括
        

1、函数的概念
    函数(function),也叫功能、方法,函数可以将一段代码一起封装起来,被封装起来的函数具备某一项特殊的功能,内部封装的一段代码作为一个完整的结构体,要执行就都执行,要不执行就都不执行
    函数的作用就是封装一段代码,将来可以重复使用
2、函数声明和调用
    函数声明又叫函数定义,函数必须先定义然后才能使用
    如果没有定义函数直接使用,会出现一个引用错误
    函数声明语法:
        function 函数名 (参数) {
            封装的结构体;
        }
    特点:函数声明的时候,函数体并不会执行,只有当函数被调用的时候才会执行
    函数调用方法:函数名();
    函数调用也叫函数执行,调用时会将函数内部封装的所有结构体的代码立即执行
    函数内部语句执行的位置,与函数定义的位置无关,与函数调用的位置有关
    函数可以一次调用,多次执行
3、函数的参数
    我们希望函数执行结果不是一成不变的,可以根据自定义的内容发生一些变化
    函数预留了一个接口,专门让用户自定义内容,使函数发生一些执行结果变化
    接口:就是函数的参数,函数参数的本质就是变量,可以接收任意类型的数据,导致函数执行结果根据参数不同,结果也不同
    一个函数可以设置0个或多个参数,参数之间用逗号分隔
    函数的参数根据书写位置不同,名称也不同
    形式参数:定义的()内部的参数,叫做形式参数,本质是变量,可以接收实际参数传递过来的数据。简称形参
    实际参数:调用的()内部参数,叫做实际参数,本质就是传递的各种类型的数据,传递给每个形参,简称实参
    函数执行过程,伴随着传参的过程
    函数的参数优点
        不论使用自己封装的函数,还是其他人封装的函数,只需要直到传递什么参数,执行什么功能,没必要直到内部的结构什么
        一般自己封装的函数或者其他人封装的函数需要一个API接口说明,告诉用户参数需要传递什么类型的数据,实现什么功能
4、函数的返回值
    函数能够通过参数接收数据,也能够将函数执行结果返回一个值
    利用函数内部的一个return的关键字设置函数的返回值
    作用1:函数内部如果结构体执行到一个return的关键字,会立即停止后面代码的执行
    作用2:可以再return关键字后面添加空格,空格后面任意定义一个数字字面量或者表达式,函数再执行完自身功能之后,整体会被return矮化成一个表达式,表达式必须求出一个值可以参与程序,表达式的值就是return后面的数据
    函数的返回值应用
        函数如果有返回值,执行结果可以当成普通数据参与程序
        函数如果有返回值,可以作为一个普通数据赋值给一个变量,甚至赋值给其他函数的实际参数
        注意:如果函数没有设置return语句,那么函数有默认的返回值undefined;如果函数使用return语句,但是return后面没有任何值,那么函数的返回值也是undefined
5、函数表达式
    函数表达式是函数定义的另一种方式
    定义方法:就是将函数的定义、匿名函数赋值给一个变量
    函数定义赋值给一个变量,相当于将函数整体矮化成了一个表达式
    匿名函数:函数没有函数名
    调用函数表达式,方法是给变量名加()执行,不能使用函数名加()执行
        var foo = function fun() {
            console.log(1);
        };
6、函数的数据类型
    函数是一种单独的数据类型Function
    由于函数是一种数据类型,可以参与其他程序
    例如,可以把函数作为另一个函数的参数,在另一个函数中调用
    或者,可以把函数可以作为返回值从函数内部返回
7、arguments对象
    JavaScript中,arguments对象是比较特殊的一个对象,实际上是当前函数的一个内置属性。也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。arguments是一个伪数组,因此及可以进行遍历
    函数的实参个数和形参个数可以不一致,所有的实参都会存储在函数内部的arguments类数组对象中
8、函数递归
    函数内部可以通过函数名调用函数自身的方式,就是函数递归现象
    递归的次数大多容易出现错误:超出计算机的最大计算能力
    更多的时候,使用递归去解决一些数学中的现象
    例如可以输出斐波那契数列的某一项的值;后面一项是前两项数据之和
9、作用域
    作用域:变量可以起作用的范围
    如果变量定义在一个函数内部,只能在函数内部被访问到,在函数外部不能使用这个变量,函数就是变量定义的作用域
    任何一对花括号{}中的结构体都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域
    在es6之前没有块级作用域的概念,只有函数作用域,现阶段可以认为JavaScript没有块级作用域
    局部变量:定义在函数内部的变量,只能在函数作用域内部被访问到,在外面没有定义的
    全局变量:从广义上来讲,也是一种局部变量,定义在全局的变量,作用域范围是全局,在整个js程序任意位置都能被访问到
    变量推出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁
10、参数和函数的作用域
    函数的参数本身也是一个变量,也有自己的作用域,函数的参数也属于函数自己内部的局部变量,只能在函数内部被使用,在函数外面没有定义
    函数也有自己的作用域,定义在哪个作用域内部,只能在这个作用域范围内被访问,出了作用域不能被访问
    函数定义在另一个函数内部,如果外部函数没有执行时,相当于内部代码没写
11、作用域链和遮蔽效应
    只有函数可以制造作用域结构,那么只要是代码,就至少有一个作用域,即全局作用域。凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
    将这样的所有的作用域列出来,可以有一个结构:函数内指向函数外的链式结构。就称作作用域链
    遮蔽效应:程序在遇到一个变量时,使用时作用域查找顺序,不同层次的函数内部都能有可能定义相同名字的变量,一个变量在使用时,会优先从自己所在的层作用域查找变量,如果当前层没有变量定义会按照顺序从本层往外依次查找,直到找到第一个变量定义。整个过程中会发生内层变量遮蔽外层变量的效果,叫做“遮蔽效应”
12、不写var关键字的影响
    在函数内部想要定义新的变量,如果不加关键字var,相当于定义的全局变量。如果全局也有相同的标识符,会被函数内部的变量影响,局部变量污染全局变量
    注意:每次定义变量时都必须写var关键字,否则就会定义在全局,可能污染全局
13、预解析
    JavaScript代码的执行是由浏览器中的JavaScript解析器来执行的。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程
    预解析过程:
        1、把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值
        2、把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用
        3、先提升var,再提升function
    JavaScript的执行过程:在解析之后,根据新的代码顺序,从上往下按照既定规律执行js代码
    变量声明提升
        在预解析过程中,所有定义的变量,都会将声明的过程提升到所在的作用域最上面,在将来的代码执行过程中,按照先后顺序会先执行被提升的声明变量过程
        提升过程中,只提升声明过程,不提升变量赋值,相当于变量定义未赋值,变量内存储undefined值
        因此,在js中会出现一种现象,在前面调用后定义的变量,不会报错,只会使用undefined值
    函数声明提升:
        在预解析过程中,所有定义的函数,都会将声明的过程提升到所在的作用域最上面,在将来的代码执行过程中,按照先后顺序会先执行被提升的函数声明过程
        在预解析之后的代码执行过程中,函数定义过程已经在最开始就会执行,一旦函数定义成功,后续就可以直接调用函数
        因此,在js中会出现一种现象,在前面调用后定义的函数,不会报错,而且能正常执行函数内部的代码
    提升顺序
        解析过程中,先提升var变量声明,再提升function函数声明
        假设出现变量名和函数名相同,那么后提升的函数名标识符会覆盖先提升的变量名,那么在后续代码中出现调用标识符时,内部时函数的定义过程,而不是undefined。
        如果调用标识符的过程在源代码函数和变量定义后面,相当于函数名覆盖了一次变量名,结果在执行到变量赋值时,又被新值覆盖了函数的值,那么在后面再次调用标识符,用的就是变量存的新值
        建议:不要书写同相同的标识符给变量名或函数名,避免出现覆盖
    函数表达式的提升
    在解析过程中,函数表达式进行的是变量声明提升,而不是函数声明提升。提升后变量内部存的是一个undefined。在前面进行函数方法调用,数据类型会提示错误
    建议:定义函数,最好使用function关键定义方式,这样函数声明提升可以永远生效
    函数声明提升的应用
        函数声明提升可以用于调整代码的顺序,将大段的定义过程放到代码最后,但是不影响代码执行结果
14、IIFE自调用函数
    IIFE:immediately-invoked function expression ,叫做即时调用的函数表达式,也叫自调用函数,表示函数在定义时就立即调用
    函数调用方式:函数名或函数表达式的变量名后面加()运算符
    函数名定义的形式不能实现立即执行自调用,函数使用函数表达式形式可以实现立即执行,原因是因为函数表达式定义过程中,将一个函数矮化成了一个表达式,后面加()运算符就可以立即执行
    启发:如果想实现IIFE,可以想办法将函数矮化成表达式
    函数矮化成表达式,就可以实现自调用
    函数矮化成表达式的方法,可以让函数参与一些运算,也就是说给函数前面加一些运算符
        数学运算符: + - ()
        逻辑运算符:! 非运算
    IIFE结构可以关住函数的作用域,在结构外面是不能调用函数的
    IIFE最常用的是()运算符,而且函数可以不写函数名,使用匿名函数
        (function(a){
            console.log(a);
        })(1);
 

标签:函数,对象,JavaScript,笔记,拉钩,作用域,数组,字符串,变量
来源: https://blog.csdn.net/Yao_Huang_/article/details/120314187