一、构造函数与原型对象
1、构造函数
作用:主要用于创建对象,初始化对象的属性
1、ES5中创建构造函数然后创建对象
function Student(id,name){
this.id = id,
this.name = name
}
let s1 = new Student(001,'小王')
2、ES6中创建类,给类单独定义构造函数
class Student{
constructor(id,name){
this.id = id,
this.name = name
}
}
let s1 = new Student(001,'小王')
注:通常把用构造函数创建对象的过程称为类的实例化,对象就是类的实例
2、构造函数的成员或类的成员
(1)成员:类的成员包括属性、方法(行为),通常将属性称为成员变量,把方法(行为)称为成员函数(成员方法)
(2)成员变量又称为实例变量:用类或构造函数创建的对象都具有相同的属性和方法
class Person{
constructor(id,name){
this.id = id,
this.name = name
}
display(){
console.log('编号:',this.id)
console.log('姓名:',this.name)
}
}
let p1 = new Person('001','小王')
let p2 = new Person('001','小李')
注:创建的对象属性和方法相同,但他们在内存中的存储空间不同
(3)静态成员:通过构造函数名或类名直接访问的成员。不属于任何对象,为类的所有对象(实例共享的) 静态成员也称为类成员
//ES6中定义方式
class Student{
constructor(id,name){
Student.sname = '清华大学',//sname是静态成员,可通过类名直接访问,类成员为类的所有对象共享
this.id = id, //id是实例成员 ,属于具体的实例(对象)
this.name = name //name是实例成员
}
display(){
console.log('学校',Student.sname);
console.log('学号',this.id);
console.log('姓名',this.name);
}
}
let stu1 = new Student('001','小王');
stu1.display();
console.log('---------------------')
let stu2 = new Student('002','小李');
stu2.display();
console.log('---------------------')
let stu3 = new Student('003','小张');
stu3.display();
console.log('---------------------')
Student.sname = '北京大学';
stu1.display();
stu2.display();
stu3.display();
// ES5静态成员写法
function Student(id,name){
this.id = id,
this.name = name,
Student.sname = '清华大学'//静态成员
this.display = function(){
console.log('学校',Student.sname);
console.log('学号',this.id);
console.log('姓名',this.name);
}
}
(4)构造方法和类的区别
1、构造函数中定义的函数,本质是属性,需要占存储空间
2、在类中定义的函数,不是属性,不需要占用存储空间。即在创建类的对象的过程中,只给对象的属性分配存储空间,对象的函数不占空间,因此节省了内存空间
3、原型对象
(1)每个构造函数都存在一个原型对象,通过构造函数的prototype属性访问
a、构造函数的原型对象:是object类型的,通过prototype属性可以访问到
b、作用:通过原型对象可以给构造函数增加新的功能,新的功能可以被共享给构造函数所创建的所有对象
(2)对象的原型对象:js中每个对象都有一个原型对象,通过__proto__属性来获取
(3)实例对象和原型对象的关系
(4)对象的构造函数:通过对象的原型对象来获取,在对象的原型对象中有一个属性constructor属性,代表了对象的构造函数。
(5)构造函数、原型对象和实例对象之间的关系
(6)原型链
1、通过构造函数的prototype属性找到构造函数的原型对象,通过构造函数的原型对象的constructor找到构造函数
2、通过构造函数创建实例对象,通过实例对象的__proto__属性可以找到对象的原型对象,也可以通过对象的原型对象的constructor找到构造函数
把以上两种找原型对象个和构造函数的过程称为原型链
(7)原型对象的原型对象:原型对象也是一个对象,那么它也有原型对象
(8)原型链结构特点:
1、每个构造函数都有一个prototype属性指向原型对象
2、原型对象通过constructor属性指向构造函数
3、通过实例对象的__proto__属性可以访问原型对象
注:Object的原型对象的__proto__属性为null
(9)JavaScript中成员的查找机制
1、首先查找对象中有没有成员(属性)
2、如果没有找到,就继续查找原型对象的原型对象
3、如果直到最后都没有找到,则返回undefined
function Person(){
this.username = '小花'//在这里定义了Person的成员username,则下面查找
this.sayHello = function(){
console.log('Hello Monday~')
}
}
let p1 = new Person();
console.log('###',p1.username);//p1的原型对象Person中没有username这个成员,所以继续查找的Person的原型对象Object中查找 一直未找到 所以返回undefined
Object.prototype.username = '小草';//在Object的原型对象上定义username属性
console.log('---',p1.username);//在输出p1.username时会逐层向上查找 最终在Object原型对象上找到该属性 输出'小草
二、this的指向问题
1、在构造函数内部this指向新创建的对象
2、直接通过函数名调用函数时,this代表的是全局对象window对象
3、如果将函数作为对象的方法调用,this将会指向该对象
三、JavaScript中的错误处理
1、使用try-catch进行处理
try{
代码段 //有可能会产生错误
}catch(错误对象){
代码段 //产生错误后所执行的代码
}
执行过程:
(1)若try{}中的代码出现了错误,js会根据错误的类型生成错误对象,然后将该错误对象抛出去
(2)catch会接收try抛出的错误对象,然后对错误进行处理
(3)若try{}中的代码出现错误,try{}中余下的代码就停止执行,转到catch下执行
(4)最后继续执行try-catch之后的代码
let obj = {}
try {
// 生成一个error对象
let err = new Error('函数没有定义');
// obj.show();
// 将生成的err抛出
throw err;
} catch (error) {
console.log(error)
}
console.log('------------');
2、常见的错误类型
(1)Error:表示普通错误,其他的错误对象都是从该对象派生而来
(2)RangeError:数值超出有效范围
(3)ReferenceError:引用了一个不存在的变量
(4)SyntaxError:语法错误
(5)TypeError:类型错误
3、throw:是JavaScript中的关键字,用于在try中抛出错误对象
四、查找算法
1、顺序查找:按照数组集合中元素的存放顺序次数依次操作(按顺序依次比较每个元素)
let arr = [89,10,23,99,45,110]
// 在数组arr中查找一个数,找到返回其下标,若没有找到则返回-1
function findNum(arr,num){
for(let i =0;i<arr.length;i++){
if(arr[i] === num){
return i;
}
}
return -1;
}
let k = findNum(arr,99);
console.log(k);
2、折半查找(二分法查找)
(1)前提条件:被查找的集合或数组必须是有序的
(2)每次查找时先和被查找区间的中间元素进行比较,若大于中间元素,则继续在被查找区间的右区间查找,若小于中间元素,则在被查找区间的左区间中查找,如此循环,直到查找结束。