继承详情和函数进阶

继承

面向对象三大特征:封装、继承、多态

对象的拷贝(继承)

// 继承演示(对象的继承)
function extend(child, parent) {
    
    
  for (var key in parent) {
    
    
    if (child[key]) continue;  // 如果child中有该成员,不替换成parent对象中的成员
    child[key] = parent[key];
  }
}

var parent = {
    
    
  name: '王健林',
  age: 60,
  house: '别墅',
  money: 1000000,
  car: '玛莎拉蒂',
  play: function () {
    
    
    console.log('弹吉他');
  }
};

var child = {
    
    
  name: '王思聪',
  age: 18
};
// 把parent对象的所有成员 拷贝到 child对象上 (实现继承)
extend(child, parent);

原型继承

// 1 原型继承
function Super() {
    
    
  this.color = 'red';
}
function Sub() {
    
    
}

Sub.prototype = new Super();
Sub.prototype.constructor = Super;

var sub = new Sub();
console.log(sub.color);

原型继承的问题:无法给构造函数传参

借构造函数继承

function Person(name, age, sex) {
    
    
  this.name = name;
  this.age = age;
  this.sex = sex;
}
function Student(name, age, sex, score) {
    
    
  Person.call(this, name, age, sex);
  this.score = score;
}
var stu = new Student('zs', 18, '男', 100);
console.log(stu);

借用构造函数继承问题:无法重用方法

组合式继承

// 结合原型继承和组合式继承
function Person(name, age, sex) {
    
    
  this.name = name;
  this.age = age;
  this.sex = sex;
}
Person.prototype.sayHi = function () {
    
    
  console.log(this.name);
}
function Student(name, age, sex, score) {
    
    
  Person.call(this, name, age, sex);
  this.score = score;
}
Student.prototype = new Person();
Student.prototype.constructor = Student;

var stu = new Student('zs', 18, '男', 100);
console.log(stu);

函数进阶

函数的定义方式

  • 函数声明
  • 函数表达式
  • new Function

函数声明

function foo () {
    
    

}

函数表达式

var foo = function () {
    
    

}

函数声明与函数表达式的区别

  • 函数声明必须有名字。会函数提升,声明前后都可以调用。
  • 函数表达式可以没有名字,例如匿名函数。类似于变量赋值只是该变量进行提升,函数没有变量提升,必须在表达式执行之后才可以调用。

函数的调用方式

  • 普通函数
  • 构造函数
  • 对象方法

函数内 this 指向的不同场景

函数的调用方式决定了 this 指向的不同:

调用方式 this指向
普通函数调用 window
构造函数调用 实例对象
对象方法调用 该方法所属对象
事件绑定方法 绑定事件对象
定时器函数 window

函数内部的this,是由函数调用的时候来确定其指向的

函数也是对象

  • 所有函数都是 Function 的实例

call,apply,bind

  • call 和 apply 特性一样

    • 都是用来调用函数,而且是立即调用
    • 但是可以在调用函数的同时,通过第一个参数指定函数内部 this 的指向
    • call 调用的时候,参数必须以参数列表的形式进行传递,也就是以逗号分隔的方式依次传递即可
    • apply 调用的时候,参数必须是一个数组,然后在执行的时候,会将数组内部的元素一个一个拿出来,与形参一一对应进行传递
    • 如果第一个参数指定了 null 或者 undefined 则内部 this 指向 window
  • bind

    • 它和 call、apply 最大的区别是:bind 不会立即调用

例子

//让数组的每一项作为方法的参数
// Math.max(arr)不能求数组中的最大值   Math.max.apply(Math, arr)可以
var arr = [2, 1, 8, 9, 10, 3];
console.log(Math.max.apply(Math, arr));
console.log.apply(console, arr);


this.x = 9; 
var module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX(); // 返回 81

var retrieveX = module.getX;
retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域

// 创建一个新函数,将"this"绑定到module对象
var boundGetX = retrieveX.bind(module);
boundGetX(); // 返回 81

函数的其它成员

  • arguments
    • 实参集合
  • caller
    • 函数的调用者
  • length
    • 形参的个数
  • name
    • 函数的名称
    function max() {
      // 当函数的参数个数不固定的时候
      // 在函数内部,可以通过arguments获取到实际传过来的参数
      var max = arguments[0];
      for (var i = 0; i < arguments.length; i++) {
        if (max < arguments[i]) {
          max = arguments[i];
        }
      }
      return max;
    }

    console.log(max(5, 1, 3, 8, 2));

高阶函数

  • 函数可以作为参数
  • 函数可以作为返回值

作为参数

设置断点的方法:f12,Sources,在源码里点击某一行即可设置断点,f5刷新,点击f11进行下一步操作

function eat (callback) {
  setTimeout(function () {
    console.log('吃完了')
    callback()
  }, 1000)
}

eat(function () {
  console.log('去唱歌')
})

猜你喜欢

转载自blog.csdn.net/qq_41160739/article/details/117407649