Javascript第三期学习

对象

简介

只要不是字符串、数值、布尔值、空值、未定义中的数据类型,都是对象。

基本数据类型都是单一的值,值与值之间没有任何联系

在JS中来表示一个人的信息,如果使用基本数据类型的数据,我们所创建的变量都是独立的,不能成为一个整体。

对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。

对象的分类:
1.内建对象
-由ES标准中定义的对象,在任何ES的实现中都可以使用。
-比如:Math、String、Number、Boolean、Function、Object……
2.宿主对象
-由JS的运行环境提 供的对象,目前来讲主要指由浏览器提供的对象。
-比如BOM、DOM。
3.自定义对象
-由开发人员自己创建的对象。

对象的基本操作

使用new关键字调用的函数,是构造函数constructor
构造函数是专门用来创建对象的函数

var obj = new Object();

console.log(obj);

我们看看在浏览器控制台输出情况
object
我们发现在浏览器中直接输出对象的话这边只是显示一个Object为空。
但是使用typeof检查一个对象时,会返回object

在对象中保存的值称为属性,向对象添加属性
语法:
对象.属性名=属性值;
下面我们就来试试

var obj = new Object();
obj.name = "优快云";
console.log(obj);

优快云
在这里我们看到了属性name的值。
这里和Python中的字典是非常相似的。
我们怎么从Object中读取属性呢?
语法:
对象.属性名

console.log(obj.name);

这里展示了变动部分
效果
我们看到这里直接显示了name的属性值。

如果读取对象中没有的属性,不会报错而会返回undefined
修改对象的属性值
语法:
对象.属性名=新值
这里就不展示了

那么我们又怎么删除对象的属性呢
语法:
delete 对象.属性名

向对象中添加的属性名
其中属性名是不强制要求遵守标识符的规范的,但是我们还是尽量按照标识符的规范去做。
如果我们要使用特殊的属性名,不能采用.的方式来操作。
需要使用另外一种方式:
语法:
对象[“属性名”] = 属性值

var obj = new Object();
obj["123"] = 789

console.log(obj["123"]);

我们存的时候怎么存,读取时就怎么读取
我们使用[]这种形式去操作属性,更加灵活
在[]中可以直接传递一个变量,这样变量值是多少就会读取那个属性。
属性值
在JS对象的属性值,可以是任意的数据类型,甚至可以是一个对象
下面我们来测试一下

//创建一个对象
var obj2 = new Object();
obj2.name = "csdn";
//将obj2设置为obj的属性
obj.test = obj2;

console.log(obj);

下面我们来看看效果
效果
in运算符
通过in运算符可以检查一个对象中是否含有指定的属性,如果有则返回true,没有则返回false
语法:
“属性名” in 对象

基本数据类型和引用数据类型

基本数据类型:

String、Number、Boolean、Null、Undefined

引用数据类型:

Object

在JS中变量保存到栈内存中的
基本数据类型的值直接在栈内存中存储,
值与值之间是独立存在,修改一个变量不会影响其他的变量

对象是保存在堆内存中,每创建一个新对象,就会在堆内存中创建一个新空间,而变量保存的是对象的内存地址(对象的引用),如果两个对象变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另外一个也会收到影响。
展示

当比较两个基本数据类型的值时,就是比较值,
而比较量两个引用数据类型时,就是比较的对象的内存地址。
如果两个对象是一模一样的,但是地址不同,他也会返回false

对象字面量

我们一般创建对象都会像下面一样

var obj = new Object();

但是我们有一种更简单的方法来创建,我们可以使用对象字面量来创建一个对象

var obj ={};

其中的{}就是字面量
使用对象字面量,可以在创建对象时,直接指定对象中的属性
语法:

{属性名:属性值,属性名:属性值……}

对象字面量的属性名可以加引号也可以不加,如果使用一些特殊名字则必须加引号
属性名和属性值是一组一组的名值对结构,名和值之间使用:连接,对公名值对之间使用,隔开,如果一个属性后没有其他属性了,就不用写。

方法

对象属性值可以是任何数据类型,也可以是函数

使用工厂方法创建对象

我们可以使用函数方法大量快速创建结构相似的对象

function createPerson(name,age,gender){
//创建一个新对象
var obj = new Object();
//向对象中添加属性
obj.name = name;
obj.age = age;
obj.gender = gender;
obj.sayName = function(){
		alert(this.name);
}
//将新对象返回
return obj;
}

var obj

使用工厂方法创建的对象,使用的构造函数都是object,所以创建的对象都是object类型,这就导致了我们无法区分多种不同类型的对象
创建一个构造函数专门用来创建Person对象的
构造函数就是一个普通的函数,创建方式和普通函数没区别,不同的是构造函数习惯首字母大写

构造函数和普通函数的区别就是函数调用方式不同
普通函数就是直接调用,而构造函数则需要使用new关键字调用
构造函数执行流程
1.立即创建一个新对象
2.将新建对象设置为函数中this,在构造函数中可以使用this来引用新建对象
3.逐行执行代码
4 .将新对象作为返回值返回

function Person(){
	this.name="csdn";
	this.age=18;
	this.gender="男";
	this.sayName = function(){
	alert(this.name);
	};
}

使用一个构造函数创建的对象,我们称之为一类对象,也将一个构造函数称为一个类
我们可以使用instanceof检查一个对象是否是一个类的实例
语法

对象 instanceof 构造函数

如果是则返回true否则返回false

函数

简介

函数也是一个对象。
函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)。
函数中可以保存一些代码在需要的时候调用。
使用typeof检查一个函数时会返回function

那么我们如何创建一个函数对象呢?

var fun = new Function();

我们可以将要封装的代码以字符串形式传递给构造函数。
封装到函数的代码不会立即执行
函数中的代码会在函数调用时执行
调用函数语法:函数对象()

fun();

如上就是调用了之前创建的fun函数。
当我们调用函数时,函数中的代码会按照顺序执行

我们同样可以使用函数声明来创建一个函数
语法:

function 函数名([形参1,形参2……形参N]){语句……}
function fun2(){语句1;语句2}

下面我们可以使用函数表达式来创建一个函数

var 函数名 = function([形参1,形参2……形参N]){语句……}

函数的参数

我们定义一个用来求两个数和的函数
可以在函数()中来指定一个或多个形参
多个形参之间使用,隔开,声明形参就是相当于在函数内部声明对应变量,并不赋值

function sum(a,b){console.log(a+b);}

在调用函数时可以在()中指定实参(实际参数)
实参将会赋值给函数中形参
sum(1,2);
调用函数时解析器不会检查实参类型,所以要注意,是否可能会接受到非法的参数,如果可能有则需要对参数进行类型的检查。
函数的实参可以是任意数据类型。

调用函数时解析器也不会检查实参的数量,多余的实参不会被赋值。
如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined

函数返回值

创建一个函数来计算三个数和,我们只需要其返回值怎么办呢?
可以使用return来设置函数的返回值
语法:
return 值
return后面的值会作为函数的执行结果返回
如果return语句后不跟任何值就相当于返回一个undefined,如果函数中不写return则也会返回undefined

实参可以是任何值

实参可以是任意的数据类型,也可以是一个对象,当我们参数过多时可以将参数封装到一个对象中

var obj = {
name : "csdn",
age : 23,
address : "CN",
gender :"N",
};
sayHello(obj);

这样就将参数传递进去了

返回值类型

break可以退出当前循环
continue用于跳过当次循环
return可以结束整个函数
返回值可以是任意数据类型也可以是一个对象

立即执行函数

函数定义完立即执行

(function(){
	alert("我是一个匿名函数");
})();

在这里我们的匿名函数执行了
xg

ADD

函数也可以称为对象的属性
如果一个函数作为一个对象属性保存
那么我们称这个函数是这个对象的方法
调用函数就是调用对象的方法

如何枚举对象中属性呢
使用for……in语句
语法:

for(var 变量 in 对象){

}

for……in语句 对象中有几个属性循环体就会执行几次,每次执行时会将对象中的一个属性名赋值给变量

作用域

作用域指的是一个变量的作用范围
JS中有两种作用域
1.全局作用域
-直接编写在script标签的JS代码,都在全局作用域
-全局作用域在页面打开时创建,在页面关闭时销毁
-在全局作用域中有一个全局对象window,它代表一个浏览器的窗口,由浏览器创建我们可以直接使用
-在全局作用域中,创建的变量都会作为window对象的属性保存
2.函数作用域
-调用函数时创建函数作用域,函数执行完毕后销毁
-每调用一次函数就会创建一个新的函数作用域,他们之间时互相独立的
-在函数作用域中可以访问到全局变量
-当在函数作用域操作一个变量时,他会先在自生作用域中寻找,如果有则直接使用,如果没有则向上一级作用域中寻找,直到找到全局作用域,如果全局作用域中依然没有找到,则会报错ReferenceError

在函数作用域中有声明提前特性,使用var关键字声明的变量,会在函数中所有的代码执行前被声明

this

解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个参数就是this,this指向的是一个对象,这个对象我们称之为函数执行的上下文对象。
根据函数的调用方式不同,this会指向不同的对象
1.以函数形式调用时,this永远都是window
2.以方法的形式调用时,this就是调用方法的那个对象

函数修改

在我们之前的对象中我们使用了工厂批量创建,下面我们来看看其中存在的一些问题
下面写上示例

function Person(name,age,gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
	this.sayName = function(){
		alert("Hello,this is:"+this.name);
	};
}

在这里我们创建一个Person构造函数
在Person构造函数中,为每一个对象都添加了一个sayName方法,目前我们的方法多是在构造函数内部创建的,也就是说构造函数每执行一次就会创建一个新的sayName方法。
也就是说所有实例的sayName都是唯一的

原型对象

将函数定义在全局作用域中,污染了全局作用域的命名空间。而且定义在全局作用域中也很不安全

原型prototype
我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
这个属性对应着一个对象,这个对象就是我们所谓的原型对象。
如果函数作为普通函数调用prototype没有任何作用,当函数通过构造函数调用时,它创建的对象中都会有一个隐含的属性,指向构造函数的原型对象,我们可以通过__proto__来访问该属性

原型对象就相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象。
我们可以将对象中共有的内容,统一设置到原型对象中。
当我们访问对象的一个属性或方法时,他会先在对象自身中寻找,如果有则直接使用

以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样就不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了

原型对象

使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true。
可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性,使用该方法只有当对象中含有属性时,才会返回true。
原型对象也是对象,所以他也有原型,当我们使用一个对象的属性或方法时,会在自身中寻找,自身中如果有,则额直接使用,如果没有则去原型对象中寻找,自身中如果有,则直接使用,如果没有则去原型对象中寻找,如果原型对象中有则使用,如果没有,则去原型的原型中寻找。
Object对象的原型中没有对象,如果在Object中依然没有找到则返回undefined

toString()

当我们直接在页面中打印一个对象时,实际上是输出对象的toString()方法的返回值

垃圾回收 .

就像人生活一样,时间长了就会生产垃圾,程序运行过程中也会产生垃圾,这些垃圾积累过多后就会让程序运行缓慢。当一个对象没有任何变量或属性对它引用,此时我们将永远无法操作该对象,此时这种对象就是垃圾,这种对象过多会占用大量内存空间,导致程序运行变慢,所以这种垃圾必须清理。
在JS中有自动清理垃圾的回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收操作

数组

数组(Array)
数组也是一个对象,和普通对象功能类似,也是用来存储一些值
不同的是普通对象是使用字符串作为属性名,数组是使用数字作为索引操作元素
索引:从0开始的整数就是索引
数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据

var arr = new Array();

如上就是创建数组,使用typeof检查数组会返回object
向数组中添加元素
语法:

数组[索引] = 值
arr[0] = 10;

获取数组长度,可以使用length属性来获取数组长度(元素个数)
对于非连续数组使用length会获取到数组的最大索引+1
语法:

数组.length

修改length如果修改的length大于原长度,则多出来的部分会空出来
使用arr.length可以向数组最后一个位置添加元素

数组[数组.length] = 值

数组字面量

使用字面量创建数组

var arr = [];

使用字面量创建数组时,可以在创建时就指定数组的元素

var arr = [1,2,3,4,5];

这样就创建了有元素的数组
使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作为构造函数的参数传递
创建一个只有一个元素10
arr = [10];
创建一个长度为10的数组
arr2 = new Array(10);
上面的两个是不一样的
数组中的元素可以是任意的数据类型,也可以是对象

arr = [{name:"优快云"},{name:"ABCD"},{name:"EFG"}]

这样就在数组中添加了对象为元素
数组里也可以是一个函数

arr = [function(){alert(1)},function(){alert(2)}]

数组里同样也可以放数组

arr = [[1,2,3],[3,4,5],[5,6,7]]

上面称为二维数组

数组的四个方法

push()
该方法可以向数组的末尾添加一个或多个元素,并返回数组的新长度
可以将要添加的元素作为方法的参数传递,这样这些元素将会自动添加到数组的末尾
该方法会将数组新长度作为返回值返回
pop()
该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回
unshift()
向数组开头添加一个或多个元素,并返回新数组长度
向前边插入元素以后其他元素索引会依次调整
shift()
可以删除数组的第一个元素,并将被删除的元素作为返回值返回

数组的遍历

所谓的遍历数组就是将数组中所有元素都提取出来
如果使用arr[1]这种遍历就太麻烦了
下面我们使用for进行遍历

for(var i=0 ; i<arr.length ; i++){
	console.log(arr[i]);
}

我们同样可以使用

var per = new Person("csdn",18);
var per2 = new Person("ABC",19)
var perArr = [per,per2]

console.log(perArr);
遍历数组

forEach()

一般我们使用for遍历数组,在JS中还为我们提供forEach()来遍历

var arr = ["csdn","abc","def"];
**forEach()方法需要一个函数作为参数**
function fun(){
}
arr.forEach(function fun(){
console.log("hello");
});

像上面这种函数,由我们创建但是不由我们调用的,我们称之为回调函数。
数组中有几个元素函数就会被执行几次,每次执行时浏览器就会将遍历的元素以实参形式传递进来,我们可以定义形参来读取这些内容
浏览器会在回调函数中传递三个参数‘
第一个参数,当前正在遍历的元素
第二个参数就是当前正在遍历的元素索引
第三个参数就是正在遍历的数组

slice()和splice()

slice()
可以用来从数组提取指定元素
参数
1.截取开始的位置的索引
2.截取结束的位置的索引(不包括这个)(可以省略不写,这样就是从开始的位置到最后

arr.slice(0,2);
console.log(arr);

如上就是从第一个到第二个
splice()
可以删除数组中的指定元素
使用splice()会影响到原数组,会将指定元素从原数组中删除并将被删除的元素作为返回值返回
参数
第一个开始位置的索引
第二个表示删除的数量
第三个及以后可以传递新元素,这些元素会将自动插入到开始位置索引的前面

数组方法

concat()
可以连接两个或多个数组,并将新数组返回
该方法不会对原数组产生影响
join()
该方法可以将数组转换为字符串
该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回
在join()中可以指定一个字符串作为参数,这个字符串将会成为数组中元素的连接符
如果不指定连接符则默认使用,作为连接符
sort()
可以用来对数组的元素进行排序
也会影响原数组,默认会按照Unicode编码进行排序
即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码排序,所以对于数字排序时,可能会得到错误的结果
我们可以自己指定排序的规则
我们可以在sort()添加一个回调函数来指定排序规则
回调函数中需要定义两个形参
浏览器会将分别使用数组中的元素作为实参去调用回调函数
使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前面
浏览器会根据回调函数的返回值来决定元素的顺序
如果返回一个大于0的值则元素会交换位置
如果返回一个小于0的值则元素位置不会改变
如果返回一个0则认为两个元素相等,不交换位置

call和apply

call()和apply()
这两个方法都是函数对象的方法,需要通过函数对象来调用
当对函数调用call()和apply()都会调用函数执行
在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this

call()方法可以将实参在对象后依次传递
apply()方法需要将实参封装到一个数组中统一传递

this情况
1.以函数形式调用时,this永远都是window
2.以方法的形式调用时,this是调用方法的对象
3.以构造函数的形式调用时,this是新创建的那个对象
4.使用call和apply调用时,this时指定的那个对象

arguments

在调用函数时,浏览器每次都会传递两个隐含参数
1.函数的上下文对象this
2.封装实参的对象arguments
arguments时一个类数组对象,它可以通过索引来操作数据,也可以获取长度
在调用函数时,我们所传递的实参都会在arguments中保存
arguments.length可以用来获取实参的长度
我们即使不定义形参,也可以通过arguments来使用实参
arguments[0]表示第一个实参
arguments[1]表示第二个实参
它里面还有一个属性叫做callee
这个属性对应一个函数对象,就是当前正在指向的函数的对象

Date对象

在JS中使用Date对象来表示一个时间
创建一个Date对象
如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
创建一个指定的时间对象
需要在构造函数中传递一个表示时间的字符串作为参数
日期格式 月份/日/年 时:分:秒

var d2 = new Date("12/31/2022 11:10:30");

getDate()
获取当前日期对象是几日
getDay()
获取当前日期对象是周几
会返回一个0~6的值
0表示周日
1表示周一

getMonth()
获取当前时间对象的月份
会返回一个0~11的值
0表示1月
1表示2月
11表示12月

getTime()
获取当前日期的时间戳
时间戳:指的是从格林尼治或标准时间的1970年1月1日 0时0分0秒
到当前日期所花费的毫秒数
如何获取当前时间戳

time = Date.now();

Math

Math和其他的对象不同,他不是一个构造函数
它属于一个工具类不用创建对象,它里面封装了数学运算相关的属性和方法
比如
Math.PI表示的是圆周率

abs()
可以用来计算一个数的绝对值

Math.ceil()
可以对一个数进行向上取整,小数位只有有值就自动进1
Math.floor()
可以对一个数进行向下取整
Math.round()
可以对一个数进行四舍五入取整
Math.random()
可以用来生成一个0~1之间的随机数
生成一个0~10的随机数
生成一个0~X之间的随机数
Math.pow(x,y)
返回x的y次幂
Math.sqrt()
用于对一个数进行开方运算

包装类

在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
方法和属性只能添加给对象,不能添加给基本数据类型
当我们对一些基本数据类型的值去调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后在调用对象的属性和方法

字符串的方法

创建一个字符串

var str = "Hello 优快云";

我们使用console.log(str.length);
检查其长度
输出结果为13

charAt()
可以返回字符串中指定位置的字符
根据索引获取指定的字符
charCodAt()
获取指定位置字符的字符编码(Unicode编码)

String.formCharCode()
可以根据字符编码去获取字符

concat()
可以用来连接两个或多个字符串
作用和+一样

indexof()
该方法可以检索一个字符串中是否含有指定内容
如果字符串中含有该内容,则会返回其第一次出现的索引,如果没有找到指定的内容,则返回-1
可以指定第二个参数,指定开始查找的位置

lastIndexOf();
该方法的用法和indexOf()一样
不同的是indexOf是从前往后找
而lastIndexOf是从后往前找

slice()
可以从字符串中截取指定的内容
不会影响原字符串,而是将截取到的内容返回
参数:
第一个:开始位置的索引(包括开始位置)
第二个:结束位置索引(不包括结束位置)
如果传递一个负值则默认使用0
而且他还自动调整参数的位置,如果第二个参数小于第一个,则自动交换位置

substr()
用来截取字符串
参数:
1.截取开始位置的索引
2.截取的长度

split()
可以将一个字符串拆分为一个数组
参数:
需要一个字符串作为参数,将会根据该字符串去拆分数组

toUpperCase()
将一个字符串转换为大写并返回

正则表达式

正则表达式用于定义一些字符串的规则
计算机可以根据正则表达式来检查一个字符串是否符合规则
获取将字符串中符合规则的内容提取出来

创建正则表达式的对象
语法:

var 变量 = new RegExp("正则表达式"",""匹配模式");

正则表达式的方法:
test()
使用这个方法可以用来检查一个字符串是否符合正则表达式的规则
如果符合则返回true否则返回false
匹配模式中可以用
i 忽略大小写
g 全局匹配模式

正则语法

使用字面量来创建正则表达式
语法:

var 变量 = /正则表达式/匹配模式

使用字面量创建更加简单
但是使用构造函数则更加灵活
使用|表示或者的意思
[]里的内容也是或的关系
[ab]==a|b
[a-z] 任意小写字母
[A-Z] 任意大写字母
检查一个字符串中是否含有abc或aec或adc

reg = /a[bde]c/

console.log(reg.test("abc"));

[^]除了
其中加^表示除了

字符串和正则相关的方法

split()
可以将一个字符串拆分为一个数组
方法中可以传递一个正则表达式作为参数,这样方法就会根据正则表达式去拆分字符串
这个方法即使不指定全局匹配也会全都拆分

根据任意字母来将字符串拆分

search()
可以搜索字符串中是否含有指定内容
如果搜到指定内容则会返回第一次出现的索引,如果没有搜索到返回-1
它可以接受一个正则表达式作为参数,然后根据正则表达式去检索字符串

match()
可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
我们可以设置正则表达式为全局匹配模式,这样会匹配到所有的内容
可以为一个正则表达式设置多个匹配模式,且顺序无所谓

replace()
可以将字符串指定内容替换为新的内容
参数:
1.被替换的内容
2.新的内容
默认只会替换第一个

正则表达式语法

量词
通过量词可以设置一个内容出现的次数
量词只会对它前面的一个内容起作用

{n}正好出现n次
{m,n}出现m-n次
{m,}m次以上
+至少一个相当于{1,}
*0个或多个相当于{0,}
?0个或一个相当于{0,1}

检查一个字符串是否以a开头
^表示开头
$表示结尾

reg = /^a/ 匹配开头的a
reg = /a$/ 匹配结尾的a

如果在正则表达式中同时使用^$则要求字符串必须完全符合正则表达式
创建一个检查手机号合法性正则表达式
手机号规则
1开头 ^1
第二位为3~9中一个数字 [3-9]
后面的9位是任意数

var phoneReg = /^1[3-9][0-9]{9}$/;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值