Object对象
- Object类型,称为一个对象,是JavaScript中的引用数据类型
- 它是一种复合值,它将很多值聚合到一起,可以通过名字访问这些值
- 对象可以看做属性的无序集合,每个属性都是一个key-value对
对象分类
- 内建对象(由ES标准中定义的对象,在任何的ES的实现中都可以使用)
- 宿主对象(由JS运行环境提供的对象,主要由浏览器提供的对象,比如 BOM DOM)
- 自定义对象(开发人员自己创建的对象)
创建对象
- 方式1:使用内置函数创建对象
var person = new Object();
person.name = "孙悟空";
person.age = 18;
- 方式2:使用对象字面量创建对象
var obj = {};
var person = {
name: "孙悟空",
age: 18
};
对象添加属性
对象.属性名 = 属性值;
var obj = new Object();
obj.name = "孙悟空";
obj.gender = "男";
obj.age = 18;
console.log(obj);
对象属性的访问
- 方式1
对象.属性名
- 方式2
对象["属性名"]
说明:
- 中括号中可以放置变量
var obj = new Object();
obj.name = "孙悟空";
obj.gender = "男";
obj.age = 18;
console.log(obj.name);
console.log(obj.gender);
console.log(obj.age);
删除对象的属性
delete 对象.属性名;
对象的属性和属性值说明
- 对象的属性值可以是任何的数据类型
- 函数也可以作为对象的属性,称为方法
var obj = new Object();
obj.name = "孙悟空";
var obj2 = new Object();
obj2.name = "猪八戒";
obj.test = obj2;
console.log(obj.test);
console.log(obj.test.name);
in 运算符
检查一个对象中是否含有指定的属性,如果有则返回true,没有则返回false
语法:
"属性名" in 对象;
var obj = new Object();
obj.name = "孙悟空";
var obj2 = new Object();
obj2.name = "猪八戒";
obj.test = obj2;
console.log("test2" in obj);
console.log("name" in obj);
栈和堆
var a = 123;
var b = a;
a++;
var obj = new Object();
obj.name = "孙悟空";
var obj2 = obj;
obj.name = "猪八戒";
obj2 = null;
var obj3 = new Object();
var obj4 = new Object();
obj3.name = "沙和尚";
obj4.name = "沙和尚";
栈内存
变量 | 值 |
---|---|
obj4 | 0x124 |
obj3 | 0x123 |
obj2 | null |
obj | 0x000 |
b | 123 |
a | 124 |
堆内存
地址 | 值 |
---|---|
0x000 | name=“猪八戒” age = 18 |
0x123 | name=“沙和尚” |
0x124 | name=“沙和尚” |
基本数据类型和引用数据类型
var a = 123;
var b = a;
a++;
console.log("a = " + a); //124
console.log("b = " + b); //123
var obj = new Object();
obj.name = "孙悟空";
var obj2 = obj;
obj.name = "猪八戒";
console.log(obj.name); //猪八戒
console.log(obj2.name); //猪八戒
-
基本数据类型
- 值直接在栈内存中存储
- 值与值之间是独立的
- 比较两个基本数据类型的值时,就是比较值
-
引用数据类型
- 对象是保存到堆内存中的
- 每创建一个新的对象,就会在堆内存中开辟一个新的空间,变量保存的是对象的内存地址(对象的引用)
- 比较两个引用数据类型的值时,比较的是对象的内存地址
对象方法
- 如果一个函数作为一个对象的属性保存,则称这个函数为这个对象的方法
- 调用这个函数就是调用对象的方法
var obj = new Object();
obj.name = "孙悟空";
obj.age = 18;
obj.sayName = function(){
console.log(obj.name);
};
function fun(){
console.log(obj.name);
}
//调用方法
obj.sayName();
//调用函数
fun();
var obj2 = {
name: "猪八戒",
age: 18,
sayName: function(){
console.log(obj2.name);
}
};
obj2.sayName();
枚举对象中的属性
语法:
for(var 变量 in 对象){
}
说明:
- for… in 语句 对象中有几个属性,循环体就执行几次
- 每次执行时,将对象中的一个属性的名字赋值给变量
var obj = {
name: "孙悟空",
age: 18,
gender: "男",
address: "花果山"
};
for(var n in obj){
console.log("属性名: " + n);
console.log("属性值: " + obj[n]);
}
函数
- 函数也是一个对象
- 函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)
- 函数名表示函数对象
创建函数对象
- 可以将要封装的代码以字符串的形式传递给构造函数
- 封装到函数中的代码不会立即执行
- 函数中的代码会在函数调用时执行
var fun = new Function();
console.log(typeof fun); //function
var fun = new Function("console.log('我是第一个函数');");
函数的声明
语法:
function 函数名([形参1,形参2,形参3...]){
语句...
}
使用函数表达式创建函数
var 函数名 = function([形参1,形参2,形参3...]){
语句...
}
function fun2(){
console.log("这是我的第二个函数");
}
var fun3 = function(){
console.log("我是匿名函数中的代码");
};
调用函数
语法:
函数对象();
var fun = new Function("console.log('我是第一个函数');");
fun();
function fun2(){
console.log("这是我的第二个函数");
alert("呵呵");
document.write("哈哈");
}
fun2();
函数的参数
- 在函数的()中指定一个或多个形参
- 在调用函数时,可以在()中指定实参,实参会赋值给函数中对应的形参
- 调用函数时解析器不会检查实参的类型(注意,是否有可能接收到非法的参数)
- 调用函数时,解析器也不会检查实参的数量,多余实参不会被赋值,如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
- 函数的实参可以是任意的数据类型
function sum(a, b){
console.log(a + b);
}
sum(1, 2);
函数的返回值
- return后的值将会作为函数的执行结果返回,可以定义一个变量,来接收该结果
- return语句后的语句都不会执行
- 如果return语句后不跟任何值就相当于返回一个undefined
- 如果函数中不写return,则也会返回undefined
- return后可以跟任意类型的值
function sum(a, b, c){
var d = a + b + c;
return d;
}
var result = sum(1, 2, 3);
console.log("result = " + result);
/*定义一个函数,判断一个数字是否是偶数,如果是返回true,否则返回false*/
function isOu(num){
/*if(num % 2 == 0){
return true;
}else{
return false;
}*/
return num % 2 == 0;
}
var result = isOu(9);
console.log("result = " + result);
/*定义一个函数,可以根据半径计算圆的面积,并返回计算结果*/
function mianji(r){
return 3.14 * r * r;
}
var result = mianji(10);
console.log("result = " + result);
/*创建一个函数,可以在控制台输出一个人的信息
可以输出认定name age gender address*/
function sayHello(o){
console.log("我是" + o.name + ",今年我" + o.age + "岁了," + "我是一个" + o.gender + "人" + ",我住在" + o.address);
}
var obj = {
name: "孙悟空",
age: 18,
gender: "男",
address: "花果山"
};
sayHello(obj);
function sayHello(o){
console.log("我是" + o.name + ",今年我" + o.age + "岁了," + "我是一个" + o.gender + "人" + ",我住在" + o.address);
}
var obj = {
name: "孙悟空",
age: 18,
gender: "男",
address: "花果山"
};
/* 实参可以是一个函数*/
function fun(a){
a(obj);
}
fun(sayHello);
function mianji(r){
return 3.14 * r * r;
}
/* 实参可以是一个函数*/
function fun(a){
console.log("a = " + a);
}
fun(mianji(10)); //调用函数mianji取返回值作为fun的参数
说明:
函数名()
- 调用函数,相当于使用函数的返回值
函数名
- 函数对象, 相当于直接使用函数对象
/*返回值是一个对象*/
function fun2(){
//return 10;
var obj = {name: "沙和尚"};
return obj;
}
var a = fun2();
console.log("a = " + a.name);
/*返回值是一个函数*/
function fun3(){
function fun4(){
alert("我是fun4");
}
//将fun4函数对象作为返回值返回
return fun4;
//将fun4函数的执行结果(或返回值)作为返回值返回
//return fun4();
}
a = fun3();
//console.log(a);
//a();
fun3()();
立即执行函数
立即执行函数只会执行一次
(function(){
alert("我是一个匿名函数~~~");
})();
(function(a,b){
console.log("a = " + a);
console.log("b = " + b);
})(123,456);
作用域
- 一个变量的作用范围
- JS中有两种作用域
-
全局作用域
- 直接写在script标签中的js代码,都在全局作用域
- 全局作用域在页面打开是创建,在页面关闭是销毁
- 在全局作用域中有一个全局对象window, 它代表一个浏览器的窗口,它由浏览器创建,可以直接使用
- 全局作用域中, 创建的变量都会作为window对象的属性保存, 创建的函数都会作为window对象的方法保存
- 全局作用域中的变量都是全局变量,在页面的任意部分都可以访问
-
函数作用域
- 调用函数时创建函数作用域,函数执行完毕后,函数作用域销毁
- 每调用一次函数就会创建一个新的函数作用域,它们之间是相互独立的
- 函数中定义的变量,只能在函数中调用
- 当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用,如果没有则向上一级作用域中寻找,直到找到全局作用域,如果全局作用域中依然没有找到,则会报错
- 在函数中要访问全局变量,可以使用window对象
- 在函数作用域也有声明提前的特性,使用var声明的变量,会在函数中所有的代码执行之前被声明
- 函数声明也会在函数中所有代码执行之前被声明
- 定义形参就相当于在函数作用域中声明了变量
-
// 全局作用域中, 创建的变量都会作为window对象的属性保存, 创建的函数都会作为window对象的方法保存
var a = 10;
console.log(window.a);
function fun(){
console.log("我是fun函数");
}
window.fun();
变量的声明提前
- 使用var 关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值)
函数的声明提前
- 使用函数声明形式创建函数 function 函数(){},它会在所有的代码执行之前被创建,所以可以在函数声明前调用函数
- 在函数中,不使用var声明的变量都会成为全局变量
console.log("a = " + a);
var a = 123;
相当于
var a;
console.log("a = " + a);
a = 123;
fun(); //可以执行
fun2(); //不能执行
function fun(){
console.log("我是一个fun函数");
}
//函数表达式,不会被提前创建
var fun2 = function(){
console.log("我是fun2函数");
};
var a = 10;
function fun(){
var a = "我是函数中的变量a";
var b = 20;
console.log("a = " + a);
function fun2(){
console.log("a = " + a);
console.log("a = " + window.a);
}
fun2();
}
fun();
console.log("a = " + a);
console.log("b = " + b);
function fun3(){
fun4();
console.log(a);
var a = 35;
function fun4(){
alert("我是fun4");
}
}
fun3();
var c = 33;
function fun5(){
console.log("c = " + c);
c = 10;
//d没有使用var声明,则会设置为全局变量,相当于window.d
d = 100;
}
fun5();
console.log("c = " + c);
console.log("d = " + d);
var e = 23;
function fun6(e){
alert(e);
}
fun6();
debug调试
this
- 解析器在调用函数时,每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this
- this指向的是一个对象,这个对象称为函数执行的上下文对象
- 根据函数的调用方式的不同,this会指向不同的对象
- 以函数的形式调用时,this永远都是window
- 以方法的形式调用时,this就是调用方法的那个对象
function fun(){
console.log(this.name);
}
var obj = {
name: "孙悟空",
sayName: fun
};
var obj2 = {
name: "沙和尚",
sayName: fun
};
obj.sayName();
obj2.sayName();
var name = "全局的name属性";
fun();
var name = "全局";
function fun(){
console.log(this.name);
}
var obj = {
name: "孙悟空",
sayName: fun
};
var obj2 = {
name: "沙和尚",
sayName: fun
};
fun();
obj.sayName();
obj2.sayName();
工厂方法创建对象
- 使用工厂方法创建的对象,使用的构造函数都是Object,所以创建的对象都是Object这个类型,导致无法区分出多种不同类型的对象
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 obj2 = createPerson("孙悟空", 18, "男");
var obj3 = createPerson("猪八戒", 28, "男");
var obj4 = createPerson("沙和尚", 38, "男");
console.log(obj2);
console.log(obj3);
console.log(obj4);
obj4.sayName();
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;
}
function createDog(name, age){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.sayHello = function(){
alert("汪汪~~");
};
return obj;
}
var obj2 = createPerson("孙悟空", 18, "男");
var obj3 = createPerson("猪八戒", 28, "男");
var obj4 = createPerson("沙和尚", 38, "男");
var dog = createDog("旺财", 3);
console.log(dog);
console.log(obj4);
构造函数(类)
-
构造函数就是一个普通的函数,创建方式和普通函数没有区别
-
不同的是构造函数习惯上首字母大写
-
构造函数和普通函数的区别就是调用方式的不同
- 普通函数是直接调用
- 构造函数需要使用 new 关键字来调用
-
构造函数执行流程:
- 立刻创建一个新的对象
- 将新建的对象设置为函数中this(在构造函数中可以使用this来引用新建的对象)
- 逐行执行函数中的代码
- 将新建的对象作为返回值返回
- 使用同一个构造函数创建的对象,称为一类对象,也将一个构造函数称为一个类
- 将通过一个构造函数创建的对象,称为该类的实例
- 使用 instanceof 可以检查一个对象是否是一个类的实例,如果是,则返回true,否则返回false
- 所有的对象都是Object的后代 ,所以任何对象和Object做 instanceof 检查时都会返回 true
语法:
对象 instanceof 构造函数
function Person(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function(){
alert(this.name);
};
}
function Dog(){
}
var per = new Person("孙悟空", 18, "男");
var per2 = new Person("玉兔精", 16, "女");
var per3 = new Person("奔波霸", 38, "男");
var dog = new Dog();
console.log(per);
console.log(per2);
console.log(per3);
console.log(dog);
console.log(per instanceof Person);
console.log(per instanceof Object);
console.log(dog instanceof Object);
this的情况
- 当以函数的形式调用时,this是window
- 当以方法的形式调用时,谁调用方法this就是谁
- 当以构造函数的形式调用时,this就是新创建的那个对象
- 使用call和apply调用时,this是指定的那个对象
function Person(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = fun;
}
/* 将函数定义在全局作用域,污染了全局作用域的命名空间
而且定义在全局作用域中也不安全
*/
function fun(){
alert("hello,我是" + this.name);
}
var per = new Person("孙悟空", 18, "男");
var per2 = new Person("猪八戒", 28, "男");
per.sayName();
per2.sayName();
//console.log(per.sayName == per2.sayName);
arguments
- 在调用函数时,浏览器每次都会传递两个隐含的参数
- 函数的上下文对象this
- 封装实参的对象arguments
- arguments是一个类数组对象,它也可以通过索引来操作数据,也可以获取长度
- 在调用函数时,传递的实参都会在arguments中保存
- arguments.length 获取实参的长度
- 即使不定义形参,也可以通过arguments来使用实参
- arguments[0] 表示第一个实参
- arguments[1] 表示第二个实参
- arguments.callee 对应一个函数对象,就是当前正在执行的函数的对象
function fun(a, b){
//console.log(arguments instanceof Array);//false
//console.log(Array.isArray(arguments));//false
console.log(arguments.length);
console.log(arguments[0]);
console.log(arguments.callee == fun);
}
fun("hello", true);
原型(prototype)
- 每一个函数,解析器都会向函数中添加一个属性prototype
- 这个属性对应着一个对象,这个对象就是所谓的原型对象
- 当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象, 可以通过 __proto__ 来访问该属性
- 所有同一个类的实例都可以访问到这个原型对象
- 可以将对象中共有的内容,统一设置到原型对象中
- 访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用
- 创建构造函数时,可以将这些对象共有的属性和方法统一添加到构造函数的原型对象中,这样不用分别为每个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法
MyClass函数对象 | |
---|---|
prototype | 0x123 |
原型对象 (0x123) | |
---|---|
a | 123 |
__proto__ | 0x223 |
原型对象 (0x223) | |
---|---|
__proto__ |
通过MyClass创建的对象mc | |
---|---|
隐含属性 __proto__ | 0x123 |
a | 我是mc中的a |
通过MyClass创建的对象mc2 | |
---|---|
隐含属性 __proto__ | 0x123 |
通过MyClass创建的对象mc3 | |
---|---|
隐含属性 __proto__ | 0x123 |
function MyClass(){
}
MyClass.prototype.a = 123;
MyClass.prototype.sayHello = function(){
alert("hello");
};
var mc = new MyClass();
var mc2 = new MyClass();
//console.log(MyClass.prototype);
//console.log(mc2.__proto__ == MyClass.prototype); //true
mc.a = "我是mc中的a";
console.log(mc.a); //我是mc中的a
console.log(mc2.a); //123
mc.sayHello();
function Person(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
}
Person.prototype.sayName = function(){
alert("hello,我是" + this.name);
};
var per = new Person("孙悟空", 18, "男");
var per2 = new Person("猪八戒", 28, "男");
per.sayName();
per2.sayName();
- 使用对象的hasOwnProperty() 检查对象自身中是否有某个属性
function MyClass(){
}
MyClass.prototype.name = "我是原型中的名字";
var mc = new MyClass();
mc.age = 18;
console.log(mc.name);
console.log("name" in mc);
console.log(mc.hasOwnProperty("name"));//false
console.log(mc.hasOwnProperty("age"));//true
- 原型对象也是对象,所以它也有原型
- 使用一个对象的属性或方法时,会先在自身中寻找
- 如果自身中有,则直接使用
- 如果没有则去原型对象中寻找,如果原型对象中有,则使用
- 如果没有则去原型的原型中寻找,直到找到Object对象的原型
- Object对象的原型没有原型,如果在Object中依然没有找到,则返回undefined
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));
- toString()
- 直接在页面中打印一个对象时,事实上是输出的对象原型中的toString()方法的返回值
- 如果不希望输出 [object Object], 可以为对象添加一个toString()方法
function Person(name, age, gender){
this.name = name;
this.age = age;
this.gender = gender;
}
//修改Person原型的toString
Person.prototype.toString = function(){
return "Person[name=" + this.name + ", age=" + this.age + ", gender=" + this.gender + "]";
};
var per = new Person("孙悟空", 18, "男");
var per2 = new Person("猪八戒", 28, "男");
var result = per.toString();
console.log("result = " + result);
//console.log(per.__proto__.__proto__.hasOwnProperty("toString"));
console.log(per);
console.log(per2);
垃圾回收(GC)
- 当一个对象没有任何的变量或属性对它进行引用,此时永远无法操作该对象,这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢, 这种垃圾必须清理
- 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁
- 需要将不再使用的对象设置为 null 即可
函数对象的方法
- call()方法 和 apply()方法
- 当对函数调用call()和apply()都会调用函数执行
- 在调用call()和apply()可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this
- call()方法可以将实参在对象之后依次传递
- apply()方法需要将实参封装到一个数组中统一传递
function fun(a, b){
//alert(this);
console.log("a = " + a);
console.log("b = " + b);
}
var obj = {
name: "obj",
sayName: function(){
alert(this.name);
}
};
var obj2 = {
name: "obj2"
};
//fun.call();
//fun.apply();
//fun();
//fun.call(obj);
//fun.apply(obj2);
//obj.sayName.apply(obj2);
//fun.call(obj, 2, 3);
fun.apply(obj, [2, 3]);
数组(Array)
- 数组也是一个对象
- 普通对象是使用字符串作为属性名
- 数组是使用数字作为索引操作元素
- 索引
- 从0开始的整数就是索引
- 数组的存储性能比普通对象要好,在开发中经常使用数组来存储数据
- 如果读取不存在的索引,不会报错,返回undefined
索引 | 值 |
---|---|
2 | |
1 | |
0 | 10 |
- 创建数组对象
使用函数创建数组
var arr = new Array();
var arr = new Array(10, 20, 30);
var arr2 = new Array(10);//创建一个长度为10的数组
使用字面量创建数组
var arr = [];
var arr = [1, 2, 3, 4, 5, 10];
- 数组中添加元素
数组[索引] = 值;
var arr = new Array();
//console.log(typeof arr);//object
arr[0] = 10;
arr[1] = 33;
arr[2] = 22;
console.log(arr);
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
console.log(arr[3]);//undefined
- 获取数组的长度(元素的个数)
数组.length;
console.log(arr.length);
-
连续的数组,使用length可以获取到数组的长度(元素的个数)
-
非连续的数组,使用length获取到数组的最大的索引+1 (尽量不要创建非连续的数组)
-
修改length
- 如果修改的length大于原长度,则多出部分会空出来
- 如果修改的length小于原长度,则多出的元素会被删除
数组.length = 值;
- 向数组的最后一个位置添加元素
数组[数组.length] = 值;
arr[arr.length] = 70;
- 数组中的元素可以是任意的数据类型
arr = ["hello", 1, true, null, undefined];
- 数组中的元素也可以是对象
arr = ["hello", 1, true, null, undefined];
var obj = {name: "孙悟空"};
arr[arr.length] = obj;
console.log(arr);
arr = [{name: "孙悟空"}, {name: "沙和尚"}, {name: "猪八戒"}];
console.log(arr[1].name);
- 数组中的元素可以是函数
arr = [function(){alert(1);}, function(){alert(2);}];
console.log(arr);
arr[0]();
- 数组中可以放数组(二维数组及多维数组)
arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]];
console.log(arr[0][1]);
数组的方法
-
push() 方法
可向数组的末尾添加一个或多个元素,并返回新的长度 -
pop() 方法
用于删除并返回数组的最后一个元素 -
unshift() 方法
可向数组的开头添加一个或更多元素,并返回新的长度(向前边插入元素以后,其它的元素索引会依次调整) -
shift() 方法
用于把数组的第一个元素从其中删除,并返回第一个元素的值
var arr = ["孙悟空", "猪八戒", "沙和尚"];
var result = arr.push("唐僧", "蜘蛛精", "白骨精", "玉兔精");
console.log(arr);
//console.log("result = " + result);
result = arr.pop();
/*console.log(arr);
console.log("result = " + result);*/
//console.log(arr);
arr.unshift("牛魔王", "二郎神");
console.log(arr);
result = arr.shift();
console.log(arr);
console.log("result = " + result);
- 数组的遍历
var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "玉兔精"];
for(i = 0; i < arr.length; i++){
console.log(arr[i]);
}
function Person(name, age, gender){
this.name = name;
this.age = age;
}
//修改Person原型的toString
Person.prototype.toString = function(){
return "Person[name=" + this.name + ", age=" + this.age + "]";
};
var per = new Person("孙悟空", 18);
var per2 = new Person("猪八戒", 28);
var per3 = new Person("红孩儿", 8);
var per4 = new Person("蜘蛛精", 16);
var per5 = new Person("二郎神", 38);
var perArr = [per, per2, per3, per4, per5];
/*创建一个函数,可以将perArr中的满18岁的Person提取出来*/
function getAdult(arr){
//创建一个新的数组
var newArr = [];
for(i = 0; i < arr.length; i++){
var p = arr[i];
if(p.age >= 18){
newArr.push(p);
}
}
return newArr;
}
var result = getAdult(perArr);
console.log("result = " + result);
- forEach()
- 支持ie8以上的浏览器
- js提供的一种遍历数组的方法
- 需要一个函数作为参数
- 这种函数,由我们创建但是不由我们调用,称为回调函数
- 数组中有几个元素函数就会执行几次,每次执行时,浏览器会将遍历到的元素以实参的形式传递进来,可以定义形参,来读取这些内容
- 浏览器会在回调函数中传递三个参数
- 第一个参数 : 当前正在遍历的元素
- 第二个参数 : 当前正在遍历的元素的索引
- 第三个参数 : 当前正在遍历的数组
var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "玉兔精"];
arr.forEach(function(value, index, obj){
console.log("value = " + value);
console.log("index = " + index);
console.log("obj = " + obj);
});
- slice() 方法
可从已有的数组中返回选定的元素
arrayObject.slice(start,end);
返回值
返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素
注:
end不写表示 从 start 到数组结尾的所有元素
索引可以传递负值,则从后往前计算
- splice() 方法
向/从数组中添加/删除项目,将指定的元素从原数组中删除,并返回被删除的元素
注:该方法会改变原始数组
语法:
arrayObject.splice(index,howmany,item1,.....,itemX);
说明:
index : 表示开始位置的索引
howmany : 表示删除的数量
第三个及以后: 可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边
var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "玉兔精"];
var arr2 = arr.slice(0,2);
//console.log(arr2);
arr2 = arr.slice(1);
arr2 = arr.slice(1,-2);
//console.log(arr2);
var result = arr.splice(1,1,"牛魔王","铁扇公主","红孩儿");
console.log(arr);
console.log(result);
var arr = [1, 2, 3, 2, 1, 3, 4, 2, 5];
//去除数组中重复的数字
for(var i = 0; i < arr.length; i++){
for(var j = i + 1; j < arr.length; j++){
if(arr[i] == arr[j]){
arr.splice(j,1);
//当删除了当前j所在的元素以后,后边的元素会自动补位,所以需要再比一次
j--;
}
}
}
console.log(arr);
-
concat() 方法
用于连接两个或多个数组
该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本 -
join() 方法
用于把数组中的所有元素放入一个字符串
语法:
arrayObject.join(separator);
separator 可选。指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符
-
reverse() 方法
用于颠倒数组中元素的顺序
注:该方法会改变原来的数组,而不会创建新的数组 -
sort() 方法
用于对数组的元素进行排序(默认按照unicode编码进行排序),该方法会改变原数组- 可以在sort()添加一个回调函数,指定排序规则,回调函数中需要定义两个形参(第一个形参表示前面的数,第二个形参表示后面的数)
- 浏览器将会分别使用数组中的元素作为实参去调用回调函数
- 浏览器会根据回调函数的返回值来决定元素的顺序,
- 如果返回一个大于0的值,则元素会交换位置
- 如果返回一个小于0的值,则元素位置不变
- 如果返回一个0,则认为两个元素相等,也不交换位置
var arr = ["孙悟空", "猪八戒", "沙和尚", "唐僧"];
var arr2 = ["白骨精", "玉兔精", "蜘蛛精"];
var arr3 = ["二郎神", "太上老君", "玉皇大帝"];
var result = arr.concat(arr2, arr3, "牛魔王", "铁扇公主");
//console.log(result);
result = arr.join("");
//console.log(typeof result);
console.log(result);
arr.reverse();
console.log(arr);
arr = ["b", "d", "e", "a", "c"];
arr.sort();
console.log(arr);
arr = [5, 4, 2, 1, 3, 6, 8, 7];
arr.sort(function(a, b){
//return a - b;//升序
return b - a; //降序
});
console.log(arr);
Date对象
- 在JS中使用Date对象表示一个时间
- 如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间
var d = new Date();
console.log(d);
//创建一个指定的时间对象
var d2 = new Date("12/03/2020 11:10:30");
console.log(d2);
Date 对象方法
-
getDate() 方法
可返回月份的某一天 -
getDay() 方法
可返回表示星期的某一天的数字 -
getMonth() 方法
可返回表示月份的数字(返回值是 0(一月) 到 11(十二月) 之间的一个整数) -
getFullYear() 方法
可返回一个表示年份的 4 位数字 -
getTime() 方法
可返回距 1970 年 1 月 1 日之间的毫秒数(时间戳)
var d = new Date();
console.log(d);
//创建一个指定的时间对象
var d2 = new Date("12/13/2020 11:10:30");
console.log(d2);
var date = d2.getDate();
var day = d.getDay();
var month = d.getMonth();
var year = d2.getFullYear();
//console.log("date = " + date);
console.log("day = " + day);
console.log("month = " + month);
console.log("year = " + year);
var time = d2.getTime();
console.log(time);
/*var d3 = new Date("1/1/1970 0:0:0");
time = d3.getTime();
console.log(time);*/
//获取当前时间戳
time = Date.now();
//console.log(time);
var start = Date.now();
for(var i = 0; i < 100; i++){
console.log(i);
}
var end = Date.now();
console.log(end - start);
Math 对象
Math和其他的对象不同,它不是一个构造函数,不用创建对象,它里面封装了数学运算相关的属性和方法
属性
Math.PI 圆周率
方法
-
abs() 方法
可返回数的绝对值 -
ceil() 方法
可对一个数进行上舍入(对一个数向上取整) -
floor() 方法
可对一个数进行下舍入(对一个数向下取整) -
round() 方法
可把一个数字舍入为最接近的整数(四舍五入取整) -
random() 方法
可返回介于 0 ~ 1 之间的一个随机数
生成一个x-y之间的随机数
Math.round(Math.random() * (y-x)) + x);
-
max() 方法
可返回多个数中的最大值 -
min() 方法
可返回多个数中的最小值 -
pow() 方法
可返回 x 的 y 次幂的值 -
sqrt() 方法
可返回一个数的平方根
console.log(Math.PI);
console.log(Math.abs(-1));
console.log(Math.ceil(1.5));
console.log(Math.floor(1.8));
console.log(Math.round(3.5));
/*for(var i = 0; i < 100; i++){
//0-10之间的随机数
//console.log(Math.round(Math.random() * 10));
//1-10之间的随机数
//console.log(Math.round(Math.random() * 9) + 1);
//生成1-6之间的随机数
console.log(Math.round(Math.random() * 5) + 1);
}*/
var max = Math.max(10, 45, 30, 20);
var min = Math.min(10, 45, 30, 20);
console.log(max);
console.log(min);
console.log(Math.pow(2, 3));
console.log(Math.sqrt(9));
包装类
在JS中为我们提供了三个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
注意:在实际应用中不会使用基本数据类型的对象
当对一些基本数据类型的值调用属性和方法时, 浏览器会临时使用包装类将其转换为对象,然后在调用对象的属性和方法,调用完以后,再将其转换为基本数据类型
-
Number
可以将基本数据类型的数字转换为Number对象 -
Boolean
可以将基本数据类型的布尔值转换为Boolean对象 -
String
可以将基本数据类型字符串转换为String对象
String相关方法
-
在底层字符串是以字符数组的形式保存的
-
String 对象属性
- length 属性 可返回字符串中的字符数目
-
charAt() 方法
可返回指定位置的字符 -
charCodeAt() 方法
可返回指定位置的字符的 Unicode 编码。这个返回值是 0 - 65535 之间的整数 -
fromCharCode()
可接受一个指定的 Unicode 值,然后返回一个字符串
语法:
String.fromCharCode(Unicode值)
-
concat() 方法
用于连接两个或多个字符串 -
indexOf() 方法
可返回某个指定的字符串值在字符串中首次出现的位置(检索一个字符串中是否含有指定内容)
如果没有找到指定的内容,则返回-1
语法
stringObject.indexOf(searchvalue,fromindex)
说明:
fromindex 可选的整数参数。规定在字符串中开始检索的位置
- lastIndexOf() 方法
可返回一个指定的字符串值最后出现的位置,在一个字符串中的指定位置从后向前搜索
语法
stringObject.lastIndexOf(searchvalue,fromindex)
说明:
fromindex 可选的整数参数。规定在字符串中开始检索的位置
- slice() 方法
可提取字符串的某个部分,并以新的字符串返回被提取的部分
语法:
stringObject.slice(start,end)
返回值
一个新的字符串。包括字符串 stringObject 从 start 开始(包括 start)到 end 结束(不包括 end)为止的所有字符
end省略,则会截取到后边所有的字符
- substring() 方法
用于提取字符串中介于两个指定下标之间的字符
语法
stringObject.substring(start,stop)
注:
- substring() 不接受负的参数(负值,则使用0)
- 可以自动调整参数的位置,如果第二个参数小于第一个,则自动交换
- substr() 方法
可在字符串中抽取从 start 下标开始的指定数目的字符
语法
stringObject.substr(start,length)
注意: ECMAscript 没有对该方法进行标准化,因此反对使用它
- split() 方法
用于把一个字符串分割成字符串数组
语法
stringObject.split(separator,howmany)
separator 支持正则表达式
var str = "1a2b3c4d5e6f";
var result = str.split(/[A-z]/);
console.log(result);
-
toLowerCase() 方法
用于把字符串转换为小写 -
toUpperCase() 方法
用于把字符串转换为大写
var str = "hello hatwuxingge";
//console.log(str.length);
//console.log(str[1]);
var result = str.charAt(6);
result = str.charCodeAt(6);
result = String.fromCharCode(73);
result = str.concat("你好", "再见");
result = str.indexOf("h", 3);
result = str.lastIndexOf("h", 5);
result = str.slice(1, 4);
result = str.slice(1);
result = str.slice(1, -1);
result = str.substring(1, 2);
result = str.substr(1, 2);
str = "abc,bcd,efg,hij";
result = str.split(",");
str = "abcdefg";
result = str.toUpperCase();
str = "ABCDEFG";
result = str.toLowerCase();
console.log("result = " + result);
//console.log(Array.isArray(result));
//console.log(result[1]);
- search() 方法
用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串
如果搜索到指定内容,则返回第一次出现的索引,如果没有搜索到返回-1
语法
stringObject.search(regexp)
str = "hello abc hello aec afc";
result = str.search(/a[bef]c/);
console.log(result);
- match() 方法
- 可在字符串内检索指定的值,或找到一个或多个正则表达式的匹配(从一个字符串中将符合条件的内容提取出来)
- 默认情况下match只会找到第一个符合要求的内容,找到以后就停止检索,可以设置正则表达式为全局匹配模式,就可以匹配到所有的内容
- 将匹配到的内容放到一个数组中返回
语法
stringObject.match(searchvalue)
stringObject.match(regexp)
str = "1a2b3c4d5e6f7A8B9C";
result = str.match(/[a-z]/gi);
console.log(result);//a,b,c,d,e,f,A,B,C
console.log(result[1]);
- replace() 方法
- 用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串
- 默认只会替换第一个
语法
stringObject.replace(regexp/substr,replacement)
str = "1a2a3a4a5e6f7A8B9C";
//result = str.replace(/[a-z]/gi, "@_@");
result = str.replace(/[a-z]/gi, "");//删除匹配内容
console.log(result);