JavaScript this指向ES5组合继承(构造函数+原型对象)错误处理

Posted YuLong~W

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript this指向ES5组合继承(构造函数+原型对象)错误处理相关的知识,希望对你有一定的参考价值。

this指向

调用方式的不同决定了this 的指向不同,一般指向我们的调用者

调用方式this指向
普通函数调用window
构造函数调用实例对象、原型对象里的方法指向实例对象
对象方法调用该方法所属对象
事件绑定方法绑定事件对象
定时器函数window
立即执行函数window

分析this指向

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

更改this指向(call、apply、bind方法)

javascript 为专门提供了一些函数方法来处理函数内部 this 的指向问题,常用的有 bind()、call()、apply() 三种方法。

方法说明使用
apply(obj,argArray)提供参数的方式是参数数组,函数返回值借助Math对象实现数组最大值、最小值
call(obj,arg1,arg2,…)提供参数的方式是参数列表,函数返回值做继承
bind(obj,arg1,arg2,…)可实现提前绑定的效果。在绑定时,还可以提前传入调用函数时的参数,返回指定this值和初始化参数改造的原函数拷贝不调用函数,但是想改变this指向,比如改变定时器内部的this指向
//改变this指向
var Person={
    name:'张三'
}
function method(a,b){
    console.log(this)
    console.log(a+","+b)
    console.log(this.name)
    console.log('---------------------')
}
method('a','b')
method.apply(Person,['a','b'])
method.call(Person,'a','b')
method.bind(Person,'a','b')() //必须得调用 否则就只是绑定了而已

在这里插入图片描述
对bind()方法再次理解:

//bind方法
function method(a,b){
    console.log(this.name+a+b)
}
var name='张三'
method('1','2') //输出结果为张三12   该方法中this指的是window
var test=method.bind({name:'李四'},'3','4') //method方法绑定了{name:'李四'}对象   
test()  //method中的 this 指向就是{name:'李四'}的对象

继承

ES6之前并没有提供 extends 继承。可以通过构造函数+原型对象模拟实现继承,被称为组合继承

构造函数实现继承父类属性

原理: 通过call()方法 将父类的this指向子类的this,这样就可以实现子类继承父类的属性

// 利用构造函数继承父类属性 (ES5)
function Father(name, age) {
    this.name = name
    this.age = age
}
function Son(name, age, score) {
    Father.call(this, name, age) //子类继承父类属性
    this.score = score
}
var son = new Son('张三', 20, 90)
console.log(son)  //输出结果:Son {name: "张三", age: 20, score: 90}

ES6中继承父属性

// 使用super继承(ES6)
class Father {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
}
class Son extends Father {
    constructor(name, age, score) {
        super(name, age)
        this.score = score
    }
}
var son = new Son('张三', 20, 90)
console.log(son)  //输出结果:Son {name: "张三", age: 20, score: 90}

原型对象实现继承父类方法

一般情况下,对象的方法都在构造函数的原型对象中设置,通过构造函数无法继承父类方法。 可将父类的实例对象作为子类的原型对象来使用

核心原理:

  • 将子类所共享的方法提取出来,让子类的 prototype 原型对象 = new 父类()
  • 本质:子类原型对象等于是实例化父类,因为父类实例化之后另外开辟空间,就不会影响原来父类原型对象
  • 将子类的 constructor重新指向子类的构造函数
// 使用原型对象继承父方法(ES5)
function Father() { }
Father.prototype.money = function () {  //通过原型对象给Father添加一个money匿名函数
    console.log(1000)
}
function Son() { }

Son.prototype = new Father() //将父类的实例对象作为子类的原型对象
Son.prototype.constructor = Son //将原型对象的constructor属性指向子类

Son.prototype.exam = function () {
    console.log(10000)
}  //为子类增加exam()方法

new Son().money()     //调用父类money()方法 输出结果:1000
new Father().exam()   //输出结果:报错 Uncaught TypeError: (intermediate value).exam is not a function
console.log(Father.prototype.exam) //子类不影响父类,父类原型对象没有exam  输出结果:undefined

ES6中继承父方法

// ES6 继承父方法
class Father {
    constructor(name, age) {
        this.name = name
        this.age = age
    }
    money = function () {
        console.log(1000)
    }
}
class Son extends Father {
    constructor(name, age, score) {
        super(name, age)
        this.score = score
    }
    exam = function () {
        console.log(10000)
    }
}
new Son().money()    //输出结果:1000
new Father().exam()  //输出结果:报错 Uncaught TypeError: (intermediate value).exam is not a function

错误处理

try catch处理

//错误处理
try{
    var o={}
    o.fun()
    console.log("hello")  //如果前面代码出错,这行不会被执行

}catch(e){ //捕获错误 e表示错误对象
    console.log(e) // 打印的是对象 结果是:TypeError: o.fun is not a function 
    console.log(e.message)  // 打印的是对象的成员  结果是: o.fun is not a function
}
console.log("hello") //如果错误被处理会执行,不会终止程序的运行  会输出:hello

throw抛出错误对象

//抛出错误对象
try{
    var e1=new Error('错误信息')  //创建错误对象
    throw e1  //抛出错误对象
}catch(e){
    console.log(e.message)  //输出错误信息
    console.log(e1===e)    //输出:true  判断e1和e是否为同一对象
}

错误类型

类型说明
Error表示普通错误,其余6种类型的错误对象都继承自该对象
EvalError调用eval()函数错误,已经弃用,为了向后兼容,低版本还可以使用
RangeError数值超出有效范围,如“new Array(-1)”
ReferenceError引用了一个不存在的变量,如“var a = 1; a + b;”(变量b未定义)
SyntaxError解析过程语法错误,如“{ ; }”“if()”“var a = new;”
TypeError变量或参数不是预期类型,如调用了不存在的函数或方法
URIError解析URI编码出错,调用encodeURI()、escape()等URI处理函数时出现

以上是关于JavaScript this指向ES5组合继承(构造函数+原型对象)错误处理的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript ES5继承ES6 class继承

面向对象JS ES5/ES6 类的书写 继承的实现 new关键字执行 this指向 原型链

js类的继承,es5和es6的方法

JavaScript高级之继承

javascript继承

详解ES5和ES6的继承