一、JavaScript对象
1. 学习Object前言
思考 :可以用什么数据类型描述一个东西的所有属性。
eg:C老师的身高,体重和脚丫子大小。
在真实的生活中的对象、属性和方法
在真实生活中,汽车是一个对象。
汽车有诸如车重和颜色等属性,也有诸如启动和停止的方法:
所有汽车都拥有同样的属性,但属性值因车而异。
所有汽车都拥有相同的方法,但是方法会在不同时间被执行。
2. JavaScript对象定义
JavaScript 的设计是一个简单的基于对象的范式。对象由属性和方法组成,一个属性包含一个属性名和一个属性值,方法就是写在对象里面的函数。
2.1 使用关键词 new创建对象
var obj = new Object();
obj.name = '大哥';
obj.age = 34;
obj.gender = true;
obj.eat = function(){
console.log('吃卤煮~~');
}
console.log(obj.name);
console.log(obj);
obj.eat();
var obj2 = new Object();
obj2.name = '大嫂';
obj2.age = 60;
obj2.gender = false;
obj.eat = function(){
console.log('吃炒肝~~');
}
2.2 使用工厂类来创建对象
function createPerson(name,age,gender){
var obj = new Object();
obj.name = name;
obj.age = age;
obj.gender = gender;
obj.eat = function(){
console.log(obj.name+'吃卤煮~~');
}
return obj;
}
var person = createPerson('大哥',34,true);
var person = createPerson('大嫂',80,false);
2.3 使用构造方法创建对象
说明:
之前实例(对象)是有限制的。它们只创建单一类型的对象。有时我们需要创建相同“类型”的许多对象的方法。
创建一种“对象类型”的方法,是使用对象构造器函数。
使用new运算符调用构造函数,可以构造一个实例对象,用法如下
var objectName = new functionName (args)
参数说明如下
- objectName:返回的实例对象的名字
- FunctionName:构造函数,与普通函数基本相同
- args:实例对象初始化配置参数列表
- 用大写首字母对构造器函数命名是个好习惯。
- 在堆内存中开辟了一个空间,存储该对象
- this指向的是当前的实例对象
- this.属性 的方式给当前对象添加属性或者方法
- 不需要return,直接将对象返回
- new的时候,构造函数会直接将对象返回,而不是通过return返回的
2.3.1 创建构造器
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
2.3.2 调用构造器
通过 new 关键词调用构造器函数可以创建相同类型的对象:
var p1 = new Person("cuihua", 18, "男");
var p2 = new Person("gangtie", 19, "女");
var p3 = new Person("huahua",20,"x");
2.3.3 为对象添加属性
//为已有的对象添加新属性:
p1.hobby = "eat";
新属性被添加到 p1,不是任何其他 Person 对象
2.3.4 为对象添加方法
//为已有的对象添加新方法:
p1.hobby = function () {
return "drink";
};
新方法被添加到 p1,不是任何其他 Person 对象。
思考:
如果在构造函数中return了一个基本数据类型和一个引用类型对象,那么构造方法返回的是什么?
2.3.5 JavaScript内建构造器
JavaScript 提供用于原始对象的构造器:
var x1 = new String(); // 一个新的 String 对象
var x2 = new Number(); // 一个新的 Number 对象
var x3 = new Boolean(); // 一个新的 Boolean 对象
var x4 = new Array(); // 一个新的 Array 对象
var x5 = new Function(); // 一个新的 Function 对象
var x6 = new Object(); // 一个新的 Object 对象
var x7 = new Date(); // 一个新的 Date 对象
var x8 = new RegExp(); // 一个新的 RegExp 对象
var x9 = new Error(); // 一个新的 Error 对象
此外,还有一些内建的非构造器对象,如 Math 和 JSON,它们不需要使用 “new” 关键字来实例化。
2.4 对象字面量创建对象。
这是创建对象最简单的方法。
使用对象文字,您可以在一条语句中定义和创建对象。对象文字指的是花括号 {} 中的名称:值对(比如 age:18)。
var person = {name:"red romance", age:18, color:"yellow"};
也可以折行书写
var person = {
name:"red romance",
age:18,
color:"green"
};
3. JavaScript对象属性
-
属性指的是与 JavaScript 对象相关的值。
-
JavaScript 对象是无序属性的集合。
-
属性通常可以被修改、添加和删除
3.1 定义JavaScript的属性
-
对象的属性是由键值对组成的
-
每个键值对,键和值之间用 :分隔 name:‘zs’
-
所有的键都被称作是这个对象的属性,值叫做属性值
-
对象的属性,本质上都是字符串,只不过大部分时候是可以省略引号不写的;少数情况会出现不符合命名规范的,就必须带引号。
eg:‘man-type’:‘渣男马’ //这个属性名必须使用引号;属性名不是合法的js标识符就得带引号
var obj = {
name:'马志强',
'age':34,
gender:'female',
"height":175,
eat:function(){
console.log('吃货~');
},
'character-type':'渣男'//这个属性名必须使用引号;属性名不是合法的js标识符就得带引号
};
3.2 属性的增和改
通过简单的赋值,向已存在的对象添加新属性,有2种访问方式:
-
属性的点语法
点语法,写起来简单,但是某些场合无法使用.去操作
-
obj.weight = 90;
有则更改,无则添加 -
下面两种情况必须使用[],其余的都可以使用.语法
-
obj.character-type = '嘿嘿';
无法操作,因为.后面的属性名不合法,只能使用[]去操作
-
var a = 'aaa'; obj.a = 'bbb';
本意是要以变量当中的值为属性,添加一个‘bbb’的值 ‘aaa’:‘bbb’,这样写最终会把a当做对象的属性去操作,完全等价于obj[‘a’] = 'bbb’如果是要使用变量当中的值为属性,那么.语法也没办法操作;
-
-
-
中括号语法
obj['weight'] = 100;
有则更改,无则添加obj['character-type'] = '嘿嘿';
当对象的属性是不合法的名字必须使用[]var a = true; obj[a] = 'bbb';
如果我们需要以变量当中的值为属性去操作对象的话,必须使用[]
3.3 属性的删除
delete 关键词从对象中删除属性:
delete obj.age;
delete obj['character-type'];
delete obj[a];
- delete 关键词会同时删除属性的值和属性本身。
- 删除完成后,属性在被添加回来之前是无法使用的。
- delete 操作符被设计用于对象属性。它对变量或函数没有影响。
3.4 属性的查询
var person = {name:“red romance”, age:18, color:“yellow”};
objectName.property
eg: person.ageobjectName["property"]
eg: person[“age”]objectName[expression]
eg: x = “age”; person[x]
3.5 for…in语句遍历对象属性
语法:
for (variable in object) {
要执行的代码
}
for…in 循环中的代码块会为每个属性执行一次。
案例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>for in测试</title>
</head>
<body>
<script>
var person = {name:"Barry", age:18};
for(var x in person) {
console.log(x,person[x]);
}
</script>
</body>
</html>
4. JavaScript对象方法
4.1 创建对象方法
methodName : function() {
// 业务逻辑代码
}
4.2 访问对象方法
objectName.methodName();
案例练习:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>优化</title>
</head>
<body>
<script>
var person = {
name : "Barry",
age : 18,
getname : function() {
return "诸葛钢铁";
}
};
console.log(person.getname());
</script>
</body>
</html>
思考:如果调用方法的时候没有添加圆括号,会发生什么?
4.3 this关键字
this是一个内置的变量,this经常在函数/方法的内部去使用,this在函数外部统统代表的是window,this本质上是一个对象,this这个变量当中存储的是一个对象的地址,this主要代表的是这个函数的执行者或者调用者是谁。
this的使用场合
- 普通函数内部 一般执行的时候都是window去执行的
function fn1() {
console.log(this);
}
fn1();
-
构造函数内部 this一般代表的是构造器生成的那个对象
function Car(name,color,price){ this.name = name; this.color = color; this.price = price; this.run = function(){ console.log('5个油。。。'); } } //没有用new,那这个函数是当普通函数用的 var result = Car('奔驰','black',200000);//此时这个函数内部的this 是window //函数的返回值看的就是return,没有return就是undefined; console.log(result); //本质是在window对象上增加了name color price run属性和值 //在外部,我们就可以通过window的这个属性直接访问; console.log(color);
//有new,此时这个函数是当构造函数用的 //函数内部的this就指向了构造出来的对象,因为构造函数本身就是构造对象用的; var c1 = new Car('红旗','black',10000000); //返回值:如果没写return或者return后面是基本值,那么返回的就是实例化出来的对象本身,和return没关系 // 如果return后面是对象类型的数据,那么返回的就是对象数据,和实例化出来的对象没关系 console.log(c1); c1.run();
-
方法内部 一般调用的时候执行者都是这个方法的对象
var obj = {
eat:function(){
//称作方法
console.log(this);
console.log('吃');
}
}
obj.eat();//eat方法执行者是obj或者是函数的调用者
- 事件回调函数内部:代表的就是添加事件监听的事件源(后续DOM的时候讲解)
//在事件函数中,this指向事件源
//事件源:事件的源头,就是谁触发了这个事件
window.onload = function() {
console.log(this);
}
btn.onclick = function() {
console.log(this);
console.log(typeof this);
}
-
call和apply调用的时候,指向方法的第一个参数(后续讲解)
-
总结:
(1)在script标签(全局范围)中 (2)在普通函数中 (3)在构造函数中 (4)在对象的方法中 (5)在事件函数中 (6)在call和apply中
4.4 this的案例练习
-
1.普通函数中的this
function fn1() { console.log(this); function fn2() { console.log(this); } fn2(); } fn1();
-
2.构造函数中的this
function Animal() { console.log(this); } var cow = new Animal(); // 输出什么?
-
3.以下代码输出什么?
function fn1() { console.log(this); } var obj = { name: '老王', say: fn1 }; obj.say(); // 输出什么?
-
4.以下代码输出什么?
var obj1 = { name: '张三', say: function () { console.log(this); } }; var obj2 = { name: '李四', say: obj1.say }; obj2.say(); // 输出什么?
-
5.以下代码输出什么?
var obj = { name: '张三', wife: { name: '翠花', say: function() { console.log(this.name); } } } obj.wife.say(); // 输出什么?
5. 堆栈区别
栈(stack): 在js中,栈是用于存储基本数据类型、引用数据类型的地址或 执行环境(执行上下文context) 的一种内存区域。比如函数被调用时,都会在栈中创建一个新的上下文,并将该上下文推入栈的顶部。当函数返回时,该上下文将被弹出栈。
栈的特点是先进后出,FILO(first in,last out)
优点:存取速度比堆快。
缺点:空间小。
栈内存通常用于以下几种类型的值:
- 基本类型值(如数字、布尔值、字符串等)
- 函数调用上下文
堆(heap): 在js中,堆是存储引用数据类型的地方,它是一个无序的内存池。堆内存的分配和回收都是由 JavaScript 的垃圾回收机制自动进行的,程序员无需显式地分配和释放内存。
当程序创建一个对象时,JavaScript 引擎会将其存储在堆内存中,并返回该对象的地址,而这个地址一般被保存在栈内存中。
优点:空间较大。
缺点:存取速度相对较慢。
js中的堆内存通常会存储以下几种类型的对象:
- 对象
- Array 对象
- Function 对象
- DOM 对象
- 自定义对象等
5.1 基本数据类型使用
var a = 10;
var b = a;
b = 20;
console.log(a);
console.log(b);
下图演示了这种基本数据类型赋值的过程:
b获取的是a值得一份拷贝,虽然,两个变量的值相等,但是两个变量保存了两个不同的基本数据类型值。
b只是保存了a复制的一个副本。所以,b的改变,对a没有影响。
5.2 引用数据类型
引用类型是存放在堆内存中的,在栈内存中保存的实际上是对象在堆内存中的引用地址,通过这个引用地址可以快速查找到保存中堆内存中的对象
var obj1 = new Object();
var obj2 = obj1;
obj2.name = "我有名字了";
console.log(obj1.name); // 我有名字了
其实这两个引用数据类型指向了同一个堆内存对象。obj1赋值给obj2,实际上是这个堆内存对象在栈内存的引用地址复制了一份给了obj2,所以他们共同指向了同一个堆内存对象,所以修改obj2其实就是修改堆内存中的那个对象,所以通过obj1访问也能访问的到。
5.3 案例练习
如果是基本数据类型,赋值的时候直接赋的就是基本的数据值,而且是直接存储在栈里
如果是引用数据类型,把它赋值给变量的时候,赋值的是这个对象数据的地址
-
var arr = [1,2,3]; var arr1 = arr; arr[1] = 22; console.log(arr); console.log(arr1);
-
var arr = [1,2,3]; var arr1 = arr; arr = [1,22,3]; console.log(arr1);
5.4 函数执行上下文
基本数据传参和引用数据传参区别
-
var a = 10; function foo(a) { var b = 10; console.log(b); a = 20; console.log(a); } foo(a); console.log(a); console.log(b);
案例练习:
-
//基本数据传参 var a = 10; var b = 20; function add(a) { a = 40; b = 50; console.log(a, b); } add(a); console.log(a,b);
-
//引用数据类型传参 var a = [1,2,3]; function fn1(arr) { arr[1] = 666; console.log(arr); } fn1(a); console.log(a);
总结:
1、程序一开始执行,碰见了全局执行环境,首先会创建全局执行环境并且进行压栈,全局代码执行的时候依赖的就是全局执行环境当中的东西;比如 全局变量(全局变量如果存的是基本数据类型,那么这个值是直接存在栈当中的,如果这个变量存的是对象类型(函数、数组、object),那么数据是要在堆结构当中开辟自己的空间专门存储的。然后把堆里面这块空间的地址存给栈当中的对应变量);
2、当程序执行碰到了函数调用;函数是比较特殊,因为它也可以执行;函数执行的时候也要有自己的环境去依赖。因此函数执行也是创建自己的函数执行环境进行压栈(函数执行环境一定是压在全局执行环境之上的),局部变量是在函数环境当中存在的,只有函数执行,局部变量才会出现。函数执行完成以后,函数执行环境要弹出栈(销毁归还内存),局部变量也就不复存在了。
3、当函数调用完成以后,会继续执行全局代码,一直到所有的代码都执行完成,代表程序执行结束,程序结束的时候,我们的全局执行环境最后出栈。
4、堆中的对象不会自己自动删除 而是等待着垃圾回收机制进行回收。
5.4 new关键字的作用
function Dog(name,age,color){
this.name = name;
this.age = age;
this.color = color;
this.eat = function(){
console.log('吃肉');
}
}
var result = Dog('小黄',3,'yellow');
var d1 = new Dog('小黑',2,'black');
1、开辟内存空间(堆)
2、this指向该内存(让函数内部的this)
3、执行函数代码
4、生成对象实例返回(把空间的地址返回)
7. call和apply方法
7.1 概念
任何函数都有apply和call方法;
function fn1() {
console.log(this);
}
fn1(); //普通函数调用,函数内部的this指向window对象
var obj = {name: '高启强'};
fn1.call(obj); //通过call调用的时候,函数内部的this指向call()的第一个参数
fn1.apply(obj);
call和apply可以让一个对象执行另外一个对象的方法;
apply和call可以使用第一个参数传对象,让函数或者方法的执行者(this)指向这个对象;
apply和call方法中的this代表方法中的第一个参数对象。
7.2 语法
函数或者方法.apply(对象,[函数的参数]);
函数或者方法.call(对象,函数的参数1,函数的参数2);
7.3 过程
call和apply做了两件事:
1、调用的时候先把this指向改为你指定的第一个参数对象
2、然后再去自动执行使用的方法
7.4 案例
- 没有参数
var obj = {
name:'马坚强',
age:33
}
function Dog(name,age){
this.name = name;
this.age = age;
}
var d1 = new Dog('旺财',3);
d1.eat = function(){
console.log('吃肉');
}
d1.eat();
obj.eat(); // 思考报错原因
-
解决策略
-
//给这个对象自己添加一个吃肉的方法 obj.eat = function(){ console.log('吃肉'); } obj.eat();
-
//不给这个对象添加,而是使用apply或者call借用 狗的吃肉方法去实现 d1.eat.apply(obj); //把狗的eat方法调用时的this指向修改为obj,代表obj在执行狗的这个方法 d1.eat.call(obj);
-
-
有参数
Dog.prototype.eat = function(a,b){ console.log(this); console.log('吃肉'); console.log(a,b); } var d1 = new Dog('旺财',3); d1.eat(10,20); d1.eat.apply(obj,[100,200]); d1.eat.call(obj,100,200);
7.5 区别
在借调的方法需要传参的时候:apply()的参数,需要用数组传递
//区别:apply()的参数,需要用数组传递
dog.eat.call(p1, '馒头', 3);
dog.eat.apply(p1, ['包子', 5]);
7.6 笔试题
-
写一个函数,然后使用call方法改变函数中的this指向
-
请简要说明call和apply方法的作用
call和apply方法都是用来调用函数的,它们的作用是改变函数的this指向。 call方法的第一个参数是要改变this指向的对象,后面是一个参数列表,每个参数将作为函数的参数传递进去。 apply方法的第一个参数是要改变this指向的对象,第二个参数是一个数组,数组中的每个元素将作为函数的参数传递进去。 两者的区别在于传递参数的方式不同。如果已知要传递的参数是具体的值,可以使用call方法,如果要传递的参数是一个数组,可以使用apply方法。
8. Json对象
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写。
现在我们大多数都是通过json进行前后端数据交互的,json本质上是一个字符串,简称json串
前端往后台传数据的时候,要传json格式的数据json串
在前端json串的格式原形就是对象或者数组;所以我们会先把数据存储为对象或者数组,然后转化为json串进行传递。
JSON 是 JS 对象的字符串表示法,它使用文本表示一个 JS 对象的信息,本质是一个字符串。
JSON对象包含两个方法:
- JSON.stringify():将JavaScript对象转换为JSON字符串。
- JSON.parse():将JSON字符串转换为JavaScript对象。
JSON字符串的规则:
- 数据在名称与值之间使用冒号分隔,名称使用双引号括起来
- 数据以逗号分隔
- 数组用中括号[]表示,对象用大括号{}表示
- 字符串使用双引号括起来
- 数字、布尔值、null不需要引号
eg:
var obj = {a: ‘Hello’, b: ‘World’}; //这是一个对象,注意键名也是可以使用引号包裹的
var json = ‘{“a”: “Hello”, “b”: “World”}’; //这是一个 JSON 字符串,本质是一个字符串
var a = '阿马';
var b = 100;
var c = '嘿嘿';
//第一步,把数据给封成一个对象
var obj = {
a: a,
b: b,
c: c
}
//第二步,把对象给变为json串,依赖JSON对象的方法
console.log(obj);
var result = JSON.stringify(obj); //把对象转化为json串
console.log(result);
//后端传递回来的数据,我们需要把这个json串转化为对象去操作
console.log(JSON.parse(result));
练习:请根据JSON.stringify()转换数组的规则,将[1, 'hehe', true, null, 666]
转换为标准的JSON字符串。
9. 数学Math对象
-
round(), floor(),ceil()
var num = 1.4; console.log(Math.round(num)); //四舍五入取整 console.log(Math.floor(num)); //向下取整 console.log(Math.ceil(num)); //向上取整
-
max() min() abs() pow() sqrt() PI
console.log(Math.max(20, 10, 67, 44)); console.log(Math.min(20, 10, 67, 44)); console.log(Math.pow(2, 5)); //ES5当中常用这个做幂运算 console.log(Math.abs(-5)); //求绝对值 console.log(Math.sqrt(9)); //开方根 console.log(Math.PI); //圆周率 是一个属性
-
random
//拿的是0 - 1之间的一个随机数,包含0但是不包含1 console.log(Math.random()); // 我想拿到0 - 85之间的随机整数 console.log(Math.floor(Math.random()*85 + 0)) //我想拿到1 - 100之间的随机整数 console.log(Math.floor(Math.random()*99 + 1)); //我想拿到7 - 69之间的随机整数 console.log(Math.floor(Math.random()*62 + 7));
//公式: Math.floor(Math.random() * (b-a)) + a
练习:
+ 写一个函数,接受两个数字参数,返回这两个数字之间的随机整数。
+ 随机取出4个字符,作为验证码
- 写一个函数,接受两个数字参数,返回这两个数字之间的随机整数。
```js
function getRandomInt(a,b){
return Math.floor(Math.random()*(b - a + 1) + a);
}
console.log(getRandomInt(1,84));
- 随机取出4个字符,作为验证码
var str = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890';
var code = '';
for(var i = 0; i < 8; i++){
code += str[Math.floor(Math.random()*str.length)];
}
console.log(code);
10. 日期和时间对象
10.1 当做普通函数使用
var result = Date();
console.log(result);
console.log(Date.now());
10.2 当做构造器使用
var date = new Date();
console.log(date);
console.log(date.getFullYear());//拿到年
console.log(date.getMonth());//拿到月 月份是 0 - 11表示的 记得后面+1
console.log(date.getDate());//拿到日
console.log(date.getHours());//小时
console.log(date.getMinutes());//分钟
console.log(date.getSeconds());//秒
console.log(date.toLocaleTimeString());//当前时间的本地格式化字符串
console.log(date.toLocaleDateString());//当前日期的本地格式化字符串
console.log(date.getTime());//1970 年 1 月 1 日到现在 之间的毫秒数
console.log(date.getDay());//拿到星期
10.3 练习
格式化日期时间字符串 XXXX年XX月XX日
function getDateAndTimeNow(){
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth() + 1;
var day = date.getDate();
var time = date.toLocaleTimeString();
return '现在是:' + year + '年' + month + '月' + day + '日 '+ time;
}
var result = getDateAndTimeNow();
console.log(result);
11. 包装类
11.1 基本概念
我们都知道js分为基本数据类型和引用数据类型。
基本数据类型数据可以有属性吗?答案是没有,但是为什么基本数据类型却可以调用一些方法呢。
var str = "hello world";
var len = str.length;
console.log(len); //得出结果为11
明明没有却可以调用length的属性,就是因为包装类的原因,引擎在执行的前一刻发现你写的代码其实是存在问题的,在将一个字符串当做对象来使用,但是因为js是解释型语言,系统会为你进行包装类的操作。
js中提供了三种特殊的引用类型(String Number Boolean)每当我们给基本数据类型赋属性值时 引擎都会给我们自动转换,调用包装类
var str="hello word";
//var str = new String("hello world"); // 1.创建出一个和基本类型值相同的对象
//var long = str.length; // 2.这个对象就可以调用包装对象下的方法,并且返回结果给long变量
//str = null; // 3.之后这个临时创建的对象就被销毁了
var long=str.length; //因为str没有length属性 所以执行这步之前后台会自动执行以上三步操作
console.log(long); // (结果为:10)
var a = 100;
a.toString执行到这一行的时候的步骤
1、a = new Number(a); 先把数字基本值转化为包装对象
2、a.toString; 调用的其实是包装对象的原型当中的toString方法
3、调用结束后自动再让a变回基本值 a = 100;
var a = 100;
console.log(a);
console.log(a instanceof Object);
console.log(a.toString());
console.log(a instanceof Object);
包装对象一共有三种:数字 字符串 布尔值
var a = 100;
var b = new Number(100);//就是数字的包装对象
console.log(a);
console.log(b);
11.2 字符串内建方法
//所有字符串方法都会返回一个新的字符串
//对原字符串不会有任何影响
var str = 'I Love You';
console.log(str);
//(1) toLowerCase() 全小写
//功能: 把字符串转化为小写
//参数:无
//返回值:返回转化后的字符串,也是新串
console.log(str.toLowerCase());
//(2) toUpperCase() 全大写
//功能: 把字符串转化为大写
//参数:无
//返回值:返回转化后的字符串,也是新串
console.log(str.toUpperCase());
//(3) indexOf() 查找字符或字符串的位置
//注意:找到的位置有可能是0,所以写if判断的时候要小心
//功能:从原串当中找指定的子串,求出子串下标位置
//参数:1、指定的一个子串
// 2、起始位置从哪开始查找 默认是从左边第一个开始往右
// 3、找到第一个就停止查找
//返回值:返回对应的子串下标,如果没有找到返回-1
var str = 'I Love You';
console.log(str.indexOf('I'));
console.log(str.indexOf('Y'));
console.log(str.indexOf('Love'));
console.log(str.indexOf('h'));//没找到返回-1
console.log(str.indexOf('o'));//3,返回从左到右,第一个o的位置
//(4) lastIndexOf() 反向查找字符串所在位置
console.log(str.lastIndexOf('o'));//8,从右到左,第一个o的位置
//(5) split() 以指定字符切割字符串为数组
//功能:以指定字符为间隔(切割点)将字符串转化为数组
//参数:可以不写,那么整个字符串作为数组的一个元素
//可以是空串,那么每个单独的字符都会成为数组的一个元素
//可以是指定的字符串,会以这个字符串为切割点去切割
//如果没有这个切割点,和不传一样
//返回值:返回生成的数组
var res = str.split('#');
console.log(res);
//(6) slice() 字符串截取
//功能:从原串当中截取的字符串,形成新串
//参数:指定起始位置和结束位置,位置可以是负数
// 包含起始位置的但是不包含结束位置的
// 参数也可以只写一个,代表起始位置,结束位置不写代表一直截到末尾
// 前大后小,返回空字符串
//返回值:返回截取的字符串
var str = 'abcdefg';
console.log(str.slice(1));
console.log(str.slice(-2));
console.log(str.slice(1, 3));
console.log(str.slice(3, 1)); //''
console.log(str.slice(-3, -1));
console.log(str.slice(-1, -3)); //''
//(7) substr() 也是字符串截取
//功能:从原串当中截取的字符串,形成新串
//参数:指定起始位置和截取的长度,位置可以是负数,
// 如果只写一个起始位置,默认截取到末尾
// 长度<=0,返回空字符串
//返回值:返回截取的字符串
console.log(str.substr(1));
console.log(str.substr(-2));
console.log(str.substr(1, 3));
console.log(str.substr(3, 1));
console.log(str.substr(-3, -1));
//(8) substring() 也是字符串截取
//功能:从原串当中截取的字符串,形成新串
//参数:指定两个位置,两个位置不能是负数,
// 会自动的根据位置大小决定起始和结束位置
// 不包含结束位置的那个字符
//返回值:返回截取的字符串
console.log(str.substring(1));
console.log(str.substring(-2));
console.log(str.substring(1, 3));
console.log(str.substring(3, 1));
console.log(str.substring(-3, -1));
//(9) concat() 字符串拼接,可以直接用+号代替
//功能:把原串和指定的字符串拼接到一起
//参数:指定一个新的字符串
//返回值:返回拼接好的字符串
console.log(str.concat(' world'));
console.log(str + ' world');
//(10) localeCompare() 字符串比较,可以直接用比较运算符代替
//功能:比较原串和指定的字符串大小,转成Unicode码比较
//参数:指定一个字符串
//返回值:如果原串大返回1 如果原串小返回-1 如果相等返回0
var str = 'b';
console.log(str.localeCompare('a')); //1
console.log(str.localeCompare('b')); //0
console.log(str.localeCompare('c')); //-1
//(11) toString() 一般是将其他类型转换成字符串
//功能:把一个对象转化为字符串
//参数:无
//返回值:就是自己,是个新串
//(12) charAt() 根据下标获取字符内容
//功能:找到对应索引位置的字符
//参数:一个索引值
//返回值:返回找到的对应字符
console.log(str.charAt(0)); //早期都使用这个方法
console.log(str[0]); //低级浏览器不支持[]形式
//(13) charCodeAt() 返回指定字符的编码
//功能:找到对应索引位置的字符的Unicode码
//参数:一个索引值
//返回值:返回找到的对应字符的Unicode码
console.log(str.charCodeAt(0));
console.log(str.charCodeAt(1));
var str = '李泽龙';
console.log(str.charCodeAt(0));
console.log(str.charCodeAt(1));
//(14) fromCharCode() 将指定Unicode码转换成字符
//这个方法需要通过 String 来调用
console.log(String.fromCharCode(26446));
11.3 ES6新增的字符串内建方法
//1.includes(str) : 判断是否包含指定的字符串
var str = 'ajshdhak123eiuf';
console.log(str.includes('1235'));
//2.startsWith(str) : 判断是否以指定字符串开头
console.log(str.startsWith('aa'));
//3.endsWith(str) : 判断是否以指定字符串结尾
console.log(str.endsWith('ff'));
//4.repeat(count) : 重复指定次数
console.log(str.repeat(2));
//练习:输入一个字符串,保留前3位和后4位,中间用*代替
getter 和 setter
var obj = {
name: '张三',
myage: 16,
get age() {
console.log('-----有人读取了我的age');
// return 18;
return this.myage < 18 ? 18 : this.myage;
},
set age(num) {
console.log('@@@@@@有人设置了我的age');
// console.log(num);
this.myage = num;
}
}
console.log(obj);
console.log(obj.name);
console.log(obj.age);
obj.age = 800;
console.log(obj.age);
12. 正则表达式
正则表达式(regular expression)描述了一种字符串匹配的模式,可以用来检查一个字符串是否含有某种子串、将匹配的子串做替换或者从某个字符串中取出符合某个条件的子串等。说白了正则表达式就是处理字符串的,我们可以用它来处理一些复杂的字符串。更多的时候我们使用正则的意义在于判断某字符串是否符合某个规则,这个规则就是正则表达式
12.1 实例化创建对象
实例化的创建
var reg = new RegExp(pattern,flags);
pattern:正则表达式
flags:标识(修饰符),可以不写。
标识主要包括:
1. i 忽略大小写匹配
2. m 多行匹配,即在到达一行文本末尾时还会继续寻常下一行中是否与正则匹配的项
3. g 全局匹配 模式应用于所有字符串,而非在找到第一个匹配项时停止
12.2 实例化的基本使用
- 判断字符串中是否有a
var reg = new RegExp('a');
使用test方法检测函数规则
console.log(reg.test('abc'));
console.log(reg.test('bc'));
- 判断字符串中是否有ab
var reg = new RegExp('ab');
console.log(reg.test('abc'));
console.log(reg.test('acb'));
- 判断字符串中是否包含a或者b,需要忽略大小写
var reg = new RegExp('a|b','i');
console.log(reg.test('azz'));
console.log(reg.test('Azz'));
12.3 字面量创建对象
使用字面量来创建正则表达式
语法:var 变量 = /正则表达式/匹配模式
使用字面量的方式创建更加简单
var reg = /a/i;
console.log(typeof reg);
console.log(reg.test("abc"));
12.4 字面量的基本使用
-
创建一个正则表达式,检查一个字符串中是否有a或b
使用 | 表示或者的意思
var reg = /a|b|c/;
console.log(reg.test("a"));
- 创建一个正则表达式检查一个字符串中是否有字母
reg = /a|b|c|d|e|f|g|....../;
console.log(reg.test("a"));
- [abc]:查找方括号内任意一个字符。
- [^abc]:查找不在方括号内的字符。
- [0-9]:查找从 0 至 9 范围内的数字,即查找数字。
- [a-z]:查找从小写 a 到小写 z 范围内的字符,即查找小写字母。
- [A-Z]:查找从大写 A 到大写 Z 范围内的字符,即查找大写字母。
- [A-z]:查找从大写 A 到小写 z 范围内的字符,即所有大小写的字母。
reg = /[A-z]/;
console.log(reg.test("a"));
- 检查一个字符串中是否含有 abc 或 adc 或 aec
reg = /a[bde]c/;
- [^ ] 除了
reg = /[^ab]/;
reg = /[^0-9]/;
12.5 正则相关的方法
split
var str = "1a2b3c4d5e6f7";
/*
* split()
* - 可以将一个字符串拆分为一个数组
* - 方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串
* - 这个方法即使不指定全局匹配,也会全都拆分
*/
/*
* 根据任意字母来将字符串拆分
*/
var result = str.split(/[A-z]/);
console.log(result);
search
/*
* search()
* - 可以搜索字符串中是否含有指定内容
* - 如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1
* - 它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
* - serach()只会查找第一个,即使设置全局匹配也没用
*/
str = "hello abc hello aec afc";
/*
* 搜索字符串中是否含有abc 或 aec 或 afc
*/
result = str.search(/a[bef]c/);
//console.log(result);
match
/*
* match()
* - 可以根据正则表达式,从一个字符串中将符合条件的内容提取出来
* - 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索
* 我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
* 可以为一个正则表达式设置多个匹配模式,且顺序无所谓
* - match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
*
*
*/
str = "1a2a3a4a5e6f7A8B9C";
result = str.match(/[a-z]/ig);
console.log(result[2]);
replace
/*
* replace()
* - 可以将字符串中指定内容替换为新的内容
* - 参数:
* 1.被替换的内容,可以接受一个正则表达式作为参数
* 2.新的内容
* - 默认只会替换第一个
*/
str = "1a2a3a4a5e6f7A8B9C";
//result = str.replace(/[a-z]/gi , "@_@");
result = str.replace(/[a-z]/gi , "");
console.log(result);
12.6 数量修饰符
1. 通过量词可以设置一个内容出现的次数
2. 量词只对它前边的一个内容起作用
3. {n} 正好出现n次
4. {m,n} 出现m到n次,包含m和n
5. {m,} m次以上
6. + 至少一个,相当于{1,}
7. * 0个或多个,相当于{0,}
8. ? 0个或1个,相当于{0,1}
var reg = /a{3}/;
var reg = /(ab){3}/;
var reg = /b{3}/;
var reg = /ab{1,3}c/;
var reg = /ab{3,}c/;
var reg = /ab+c/;
var reg = /ab*c/;
var reg = /ab?c/;
12.7 边界修饰符
1. ^ 以...开始
2. $ 以...结尾
eg:
'^abc' 匹配以abc开头
‘abc$' 匹配以abc结尾
练习:创建一个正则表达式,用来检查一个字符串是否是一个合法手机号
- 以1开头
- 第二位3-9任意数字
- 三位以后任意数字9个
var phoneStr = "13067890123";
var phoneReg = /^1[3-9][0-9]{9}$/;
console.log(phoneReg.test(phoneStr));
12.8 单字修饰符
1. . 匹配任意字符,除了换行符
2. [] 用来表示一组字符,单独列出:[abc] 匹配 'a','b'或'c'
3. \d 匹配任意数字,等价于 [0-9].
4. \D 匹配任意非数字
5. \w 匹配字母数字及下划线
6. \W 匹配非字母数字及下划线
7. \s 匹配任意空白字符,等价于 [\t\n\r\f].
8. \S 匹配任意非空字符
12.9 邮件正则
action.haha@ abc .com.cn
var emailReg = /^\w{3,}(\.\w+)*@[A-z0-9]+(\.[A-z]{2,5}){1,2}$/;
var reg = /^\w+@[A-z0-9]+(.[A-z]{2,5}){1,2}/;
var email = "haha.hello@163.com";
console.log(emailReg.test(email));
13. 扩展
13.0 检测变量类型
-
typeof
-
instanceof
-
constructor
null、undefined没有construstor方法,因此constructor不能判断undefined和null。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> var bool = true; var num = 1; var str = 'abc'; var und= undefined; var nul = null; var s1 = Symbol(); console.log(bool.constructor === Boolean);// true console.log(num.constructor === Number);// true console.log(str.constructor === String);// true console.log(s1.constructor === Symbol);//true </script> </body> </html>
-
Object.prototype.toString.call(要检测的变量)
此方法可以相对较全的判断js的数据类型。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <script> var bool = true; var num = 1; var str = 'abc'; var und= undefined; var nul = null; var s1 = Symbol(); console.log(Object.prototype.toString.call(bool));//[object Boolean] console.log(Object.prototype.toString.call(num));//[object Number] console.log(Object.prototype.toString.call(str));//[object String] console.log(Object.prototype.toString.call(und));//[object Undefined] console.log(Object.prototype.toString.call(nul));//[object Null] console.log(Object.prototype.toString.call(s1)); //[object Symbol] </script> </body> </html>
13.1 数组
- 数组当做普通数组:
var arr = [1,2,3,4];
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
- 数组当做对象:
var arr = [1,2,3,4];
//那么A一定是对象,B一定是对象的属性,把数组当对象用加了一个属性和值
arr.heihei = 'haha';//A.B
arr['100'] = 5;
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
var arr = [1,2,3,4];
//那么A一定是对象,B一定是对象的属性,把数组当对象用加了一个属性和值
arr.heihei = 'haha';//A.B
arr['100'] = 5;
for(var key in arr){
console.log(key,arr[key]);
}
13.2 函数
- 函数当作普通函数
function fn(){
console.log('i love you');
}
//当函数去用,就是调用函数实现函数表面上的功能;一个东西加括号,那么括号前面一定函数,函数是在当函数用;
fn();
- 函数当作对象
function fn(){
console.log('i love you');
}
fn.hehe = 'heihei'; //A.B 那么代表这个函数是在当对象用;
console.log(fn);
console.dir(fn);
for(var key in fn){
console.log(key,fn[key]);
}
13.3 垃圾回收机制
栈空间的释放是代码执行完毕或者关闭页面就销毁了
堆空间的释放是靠垃圾回收机制进行的,即使关闭页面也不一定立即释放
垃圾回收的时间和方式是由js引擎和操作系统共同决定的,具体取决于当前的内存使用情况和垃圾回收策略
当函数或者整个程序执行完成后,栈里面所有的东西都被释放销毁,堆当中的数据可能还在,只是没有任何的变量指向(引用),那么堆当中的数据就会变成垃圾对象。回收机制会在适当的时候将垃圾对象清理回收;
如果我们在程序当中需要去删除对象,那么就将这个对象的变量赋值为null,代表这个对象引用被改变,这个对象也就成了垃圾对象,其实删除对象就是让堆当中的对象数据成为垃圾对象;
var a = {};
a里面存了 {}地址 a指向了{}这个对象
a = null; 把a的指向断开了;
13.4 练习案例
-
var num1 = 10; var num2 = num1; num1 = 20; console.log(num1); console.log(num2);
-
var num = 50; function f1(num) { num = 60; console.log(num); } f1(num); console.log(num);
-
var num1 = 55; var num2 = 66; function f1(num, num1) { num = 100; num1 = 100; num2 = 100; console.log(num); console.log(num1); console.log(num2); } f1(num1, num2); console.log(num1); console.log(num2); console.log(num);
-
var a = 10; var b = 20; function add(a,b){ a = 30; return a + b; } add(a,b); console.log(a); function f1(arr){ for(var i = 0; i < arr.length; i++){ arr[i] += 2 } console.log(arr); } var arr; arr = [1,2]; f1(arr); console.log(arr);
-
//两个对象是同一个对象,不同的操作有什么不同 var a = [1,2]; var b = a; a[0] = 20; // 如果a = [20,2]; console.log(b); var a = [];//new Array() var b = [];//new Array() console.log(a == b);
-
function Person(name, age, salary) { this.name = name; this.age = age; this.salary = salary; } function f1(pp) { pp.name = "ls"; pp = new Person("aa", 18, 10); } var p = new Person("zs", 18, 1000); console.log(p.name); f1(p); console.log(p.name);