美文网首页吃饭用的前端
JS原型和继承、this指向

JS原型和继承、this指向

作者: CNLISIYIII | 来源:发表于2019-05-09 21:57 被阅读0次

    (一)原型

    1.创建对象

    自定义构造函数

    function 构造函数名(参数...){
     this.key = value;
     .......
    }
    

    命名规范
    构造函数名首字母要大写 帕斯卡(每个单词首字母大写) 驼峰(从第二个单词开始首字母大写)。

    new关键字创建对象

    var 对象名 = new 构造函数名(实参...);
    

    构造函数和普通函数:

    • 相同点
      • 都是函数
    • 不同点
      • 构造函数通过new关键字调用
      • 普通函数直接调用

    2.实例对象和原型

    原型就是一个对象,原型一直都在。

    1)获取原型语法:
    构造函数名.prototype

    2)原型作用:
    节省内存。 因为原型中存放的成员(属性或方法),都可以被相关的构造函数所创建的对象共享

    3)找原型:
    首先,会从对象本身中去找;
    若对象中,找不到,则会通过__proto__所提供的原型地址,找原型;
    去原型中查找。

    代码举栗:

     // 学生类→ 构造函数
     function Student(name, age, gender) {
       // 属性
       this.name = name;
       this.age = age;
       this.gender = gender;
       // this.type = '学生'
     }
    
     // 获取原型
     // 每一个函数都有一个对应的原型
     var yx = Student.prototype;
     // 对象.key = value
     // 方法
     yx.sayHi = function () {
       // 方法内部:this 代表的是调用方法的对象
       console.log('我叫什么' + this.name)
     };
     yx.writeCode = function () {
       console.log('我会写code');
     }
     yx.type = '学生';
    
     // 创建对象
     var zs = new Student('张三', 10, '男');
     // 创建对象
     var ls = new Student('李四', 11, '男');
     // 创建对象
     var ww = new Student('王五', 17, '女');
    

    (二)原型继承

    原型继承实现时必会有下面两句代码:

    • 先更改子类的原型prototype指向一个new 父类() 对象。
      • 子类.prototype = new 父类();
    • 再给子类的原型设置一个constructor指向子类
      • 子类.prototype.constructor = 子类
    //  用于设置原型
    Employee.prototype = new Person()
    //  设置原型的构造器
    Employee.prototype.constructor=Employee
    

    代码举栗:

     // 人类 → 父类
     function Person() {
       this.name = '名字';
       this.age = 10;
       this.gender = '男';
     }
     Person.prototype.sayHi = function () { console.log('你好'); };
     Person.prototype.eat = function () { console.log('我会吃。。。'); };
     Person.prototype.play = function () { console.log('我会玩'); };
    
     // 学生类 → 子类
     function Student() {
       this.stuId = 1000;
     }
     // 子类的原型prototyp指向父类的一个实例对象
     Student.prototype = new Person();
     // 添加一个constructor成员
     Student.prototype.constructor = Student;
    
     // 如何实现原型继承:
     // 给子类的原型prototype重新赋值为父类的一个实例对象。
     // 利用了原型链上属性或方法的查找规则。
    
     // 创建一个学生对象
     var stu1 = new Student();
     console.log(stu1.constructor)
    

    (三)借用继承

    1.call方法

    • 语法:函数名.call(调用者,函数实参,函数的实参...);
    • 作用:该函数会立即执行,函数体内的this在被call时,this指向调用者。

    2.用call方法实现继承

     // 人类 → 父类
     function Person(name,age,gender) {
       this.name = name;
       this.age = age;
       this.gender = gender;
     }
     Person.prototype.sayHi = function () { console.log('你好'); };
     Person.prototype.eat = function () { console.log('我会吃。。。'); };
     Person.prototype.play = function () { console.log('我会玩'); };
    
     // 学生类 → 子类
     function Student(name,age,gender,stuId) {
       // this关键字代表谁,代表的是一个学生对象,当前创建的对象 stu1 ,stu2
       // var obj = this;
       //【借用继承】
       // Person.call(obj,name,age,gender);
       Person.call(this,name,age,gender);
       this.stuId = stuId;
     }
    
     // 创建第一个学生对象
     var stu1 = new Student('张三',10,'男',10086);
     // 创建第二个学生对象
     var stu2 = new Student('李四',11,'女',10010);
    

    (四)组合继承

     // 人类 → 父类
     function Person(name,age,gender) {
       this.name = name;
       this.age = age;
       this.gender = gender;
     }
     Person.prototype.sayHi = function () { console.log('你好'); };
     Person.prototype.eat = function () { console.log('我会吃。。。'); };
     Person.prototype.play = function () { console.log('我会玩'); };
    
     // 学生类 → 子类
     function Student(name,age,gender,stuId) {
       //【借用继承】
       Person.call(this,name,age,gender);
       this.stuId = stuId;
     }
    
     // 【原型继承】
     Student.prototype = new Person();
     Student.prototype.constructor = Student;
    
     // 创建第一个学生对象
     var stu1 = new Student('张三',10,'男',10086);
     // 创建第二个学生对象
     var stu2 = new Student('李四',11,'女',10010);
    

    (五)函数内部this指向情况总结

    1.普通函数中的this

    普通函数内部的this指向window

    function fn() {
        console.log(this); //window
    }
    fn();
    

    直接调用的函数就是普通函数

    var obj = {
      getSum: function () {
        console.log(this); //执行obj。输出obj
        function fn2() {
          console.log(this); //window
        }
      }
    };
    obj.getSum();
    

    2.定时器中的this

    只要用到定时器,setTimeout和setInerval都默认指向window

    3.构造函数

    this指向当前创建的对象

    //匿名函数一般首字母大写
    function Person() {
      this.name = 'zhang';
      this.age = 10;
      console.log(this); //Person{}
    }
    new Person();
    

    4.对象的方法

    this指向调用者

    5.事件处理程序

    this默认指向事件源

    document.onclick = function () {
      console.log(this); //document
    }
    

    (六)改变this的指向

    1.call方法

    • 语法:函数名.call(调用者,参数1,参数2...);
    • 作用:函数被借用时会立即执行,并且函数体内的this会指向借用者或调用者
      函数内部this指向谁,看函数在这一次的调用情况。
    function fn(a, b) {
      this.name = a;
        this.age = b;
    }
    fn(10, 20); //指向window,window中增加name和age
    var obj = {};
    fn.call(obj, 'zhang', 10); //obj中增加name和age,仅在这一次增加
    

    2.apply方法

    • 语法:函数名.apply(调用者,参数1,参数2...);
    • 作用:函数被借用时,会立即执行,并且函数体内的this会指向借用者或调用者
     function fn(name, age) {
       this.name = name;
       this.age = age;
     }
    
     // 对象字面量
     var obj = {};
     fn.apply(obj, ['李四', 11]);
    

    3.bind方法

    • 语法:函数名.bind(调用者,参数1,参数2...);
    • 作用:该函数被借用时,不会立即执行,而是返回一个新的函数,需要自己手动调用新函数
     function fn(name, age) {
       this.name = name;
       this.age = age;
     }
    
     // 对象字面量
     var obj = {};
     fn.bind(obj, '李四', 11);
    

    (七)函数作为函数的参数

    • 把一个函数B当做实参,传递给另一个函数的A的形参,并在函数A内部调用
      实参可以是任何类型的数据。(数字、字符串、布尔值、数组、对象、函数、undefined)。

    函数也是一种数据类型,格式是function

    相关文章

      网友评论

        本文标题:JS原型和继承、this指向

        本文链接:https://www.haomeiwen.com/subject/csmgoqtx.html