JavaScript面向对象(二)

JavaScript面向对象(二)



一、原型链

1、访问对象的原型对象:每个对象都有一个__proto__属性,这个属性指向了对象的原型对象

function Person() {}
var p1 = new Person();
console.log(p1.__proto__ === Person.prototype); // 输出结果:true

实例对象与原型对象的关系
在这里插入图片描述2、访问对象的构造函数:在原型对象里面有一个constructor属性,该属性指向了构造函数

function Person() {}
// 通过原型对象访问构造函数
console.log(Person.prototype.constructor === Person);	// 输出结果:true
// 通过实例对象访问构造函数
var p1 = new Person();
console.log(p1.constructor === Person); // 输出结果:true

案例:用赋值方式修改原型对象为新的对象,就无法访问构造器函数

function Person() {}
// 修改原型对象为一个新的对象
Person.prototype = {sayHello: function() {console.log('hello');}};
var p1 = new Person();
// 使用实例对象p1可以访问新的原型对象中的属性
p1.sayHello(); // 输出结果:hello
// 使用constructor属性无法访问原来的构造函数
console.log(p1.constructor); // 输出结果:Object() { [native code] }

构造函数、原型对象和实例对象之间的关系

在这里插入图片描述3、原型对象的原型对象

原型对象的原型对象:原型对象也是对象,那么这个对象应该也会有一个原型对象存在

function Person() {}
// 查看原型对象的原型对象
console.log(Person.prototype.__proto__);
// 查看原型对象的原型对象的构造函数
console.log(Person.prototype.__proto__.constructor);

4、原型链
①原型链结构特点

  • 每个构造函数都有一个prototype属性指向原型对象
  • 原型对象通过constructor属性指向构造函数
  • 通过实例对象的__proto__属性可以访问原型对象
  • Object的原型对象的__proto__属性为null
    ②原型链结构图
    在这里插入图片描述③函数在原型链中的结构
    在这里插入图片描述5、成员查找机制
  • JavaScript首先会判断实例对象有没有这个成员
  • 如果没有找到,就继续查找原型对象的原型对象
  • 如果直到最后都没有找到,则返回undefined
function Person() { this.name = '张三';}
Person.prototype.name = '李四';
var p = new Person();
console.log(p.name); // 输出结果:张三
delete p.name; // 删除对象p的name属性
console.log(p.name); // 输出结果:李四
delete Person.prototype.name; // 删除原型对象的name属性
console.log(p.name); // 输出结果:undefined

6、案例:利用原型对象扩展数组方法

Array.prototype.sum = function() {
  var sum = 0;
  for (var i = 0; i < this.length; i++) {
  sum += this[i];}
  return sum;
}; 
var arr = [1, 2, 3];
console.log(arr.sum()); // 输出结果:6

二、this关键字

1、分析this指向

  • 构造函数中的this指的是新创建的对象
  • 普通函数中的this指向的是window对象
  • 将函数作为对象的函数调用时this指向的是该对象

案例演示:this指向

function foo() {
  return this;
}
var o = {name: 'Jim', func: foo};
console.log(foo() === window); // 对应第2种情况,输出结果:true
console.log(o.func() === o);	// 对应第3种情况,输出结果:true

2、更改this指向:apply()方法和call()方法

  • apply(obj,argArray):
  • call(obj,arg1,arg2,…):
    apply()方法和call()方法的区别
function method(a, b) {
  console.log(a + b);
}
method.apply({}, ['1', '2']); 	// 数组方式传参,输出结果:12
method.call({}, '3', '4');		// 参数方式传参,输出结果:34

3、bind()方法:实现提前绑定的效果。在绑定时,还可以提前传入调用函数时的参数

  • bind(obj,arg1,arg2,…)

三、错误处理

1、如何进行错误处理

try{
	  
	       可能会出现错误的代码
	  
	  }catch(e){  //代码的错误类型
	  
	     错误出现后的处理代码
	  }

案例演示

var o = {};
try {// 在try中编写可能出现错误的代码
  o.func();
  console.log('a');// 如果前面的代码出错,这行代码不会执行
} catch(e) {// 在catch中捕获错误,e表示错误对象
  console.log(e);
}
console.log('b'); // 如果错误已经被处理,这行代码会执行

2、错误对象的传递

function foo1() {
  foo2();
  console.log('foo1');
}
function foo2() {
  var o = {};
  o.func();   // 发生错误
}
try {
  foo1();
} catch(e) {
  console.log('test');
}

3、抛出错误对象

try {
  var e1 = new Error('错误信息');	// 创建错误对象
  throw e1;   // 抛出错误对象,也可以与上一行合并为:throw new Error('错误信息');
} catch (e) {
  console.log(e.message);	// 输出结果:错误信息
  console.log(e1 === e);	// 判断e1和e是否为同一个对象,输出结果:true
}

4、错误类型
在这里插入图片描述在这里插入图片描述

四、继承

1、借用构造函数继承父类属性
call()方法 :将父类的this指向子类的this,这样就可以实现子类继承父类的属性。
案例

function Father(uname, age) {// Father构造函数是父类
  this.uname = uname;
  this.age = age;
}
function Son(uname, age, score) {// Son构造函数是子类
  Father.call(this, uname, age); // 子类继承父类的属性
  this.score = score; // 子类可以拥有自己的特有属性
}
var son = new Son('张三', 18, 100);
console.log(son);	// 输出结果:Son {uname: "张三", age: 18, score: 100}

2、利用原型对象继承父类方法
原型对象继承父类方法:将父类的实例对象作为子类的原型对象来使用

function Father() {}
Father.prototype.money = function() {console.log(100000);};
function Son() {}
Son.prototype = new Father(); // 将父类的实例对象作为子类的原型对象
Son.prototype.constructor = Son; // 将原型对象的constructor属性指向子类
new Son().money(); // 调用父类money()方法,输出结果:100000
Son.prototype.exam = function() {}; // 为子类增加exam()方法
console.log(Father.prototype.exam); // 子类不影响父类,输出结果:undefined

原型链示意图
在这里插入图片描述3、class语法的本质:类和构造函数的使用非常相似,可以互相替代

class Person{}
console.log(Person.prototype); // 类也有原型对象
Person.prototype.money = function() {// 类也可以增加方法
  console.log(100000);
};
new Person().money(); // 输出结果:100000

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值