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

  • Post author:
  • Post category:java




函数的调用(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



版权声明:本文为weixin_45654582原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。