JavaScript 函数的调用、this指向、ES5组合继承(构造函数+原型对象)

函数的调用(6种)

//1、普通函数
function fn(){
    
}
// fn() 或者  fn.call()

//2、对象的方法
var o={
    fn:function(){

    }
}
//o.fn()

//3、构造函数
function fn(){}
// new fn()

//4、绑定事件函数
// btn.οnclick=function(){}  点击按钮即可调用

//5、定时器函数
// setInterval(function(){},1000)  自动1秒钟调用一次

//6、立即执行函数
(function(){

})()
//自动调用

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() 三种方法。

方法说明使用
call(obj,arg1,arg2,…)调用函数,提供参数的方式是参数列表,函数返回值主要用来实现继承
apply(obj,argArray)调用函数,提供参数的方式是参数数组(包括伪数组),函数返回值借助Math对象实现数组最大值、最小值
bind(obj,arg1,arg2,…)不调用函数,提供参数方式同call(),返回指定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')() //必须得调用 否则就只是绑定了而已

在这里插入图片描述
对call()方法应用: 在构造函数实现继承父类属性例子中

对apply()方法应用: 借助Math对象对数组对象求最大值

var arr=[1,55,53,88,56]
var max=Math.max.apply(Math,arr)
console.log(max) //输出:88

对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()  //输出:李四34 method中的 this 指向就是{name:'李四'}的对象

对bind()方法应用:

//实现有一个按钮,点击后就禁用按钮,3秒之后自动开启这个按钮
//bind方法
var btn=document.querySelector('button')
btn.onclick=function(){
    this.disabled=true  //这个this指的是btn这个按钮
    setTimeout(function(){
        // this.disabled=false //这个this指的是window 因此没有效果
    }.bind(this),3000)  //这个this指的是btn这个按钮
}

继承

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指向子构造函数实例对象  子继承父属性  
    this.score = score
}
var son = new Son('张三', 20, 90)
console.log(son)  //输出结果:Son {name: "张三", age: 20, score: 90}

ES6中继承父属性:使用super关键字即可

// 使用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=Father.prototype //让子原型对象指向父原型对象 
//不能够实现,如果修改子原型,父也跟随改变

Son.prototype = new Father() //将父类的实例对象作为子类的原型对象 
//作用:实例对象存在__protp__属性可指向父类原型对象,即子类可以使用父类的方法money() 实现继承

//Son.protope.constructor此时指向的是Father构造函数
//因为利用对象的形式修改了原型对象,导致被覆盖,所以应指回Son构造函数
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
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值