JS面向对象知识点汇总

基本数据类型——undefined出现的情况:

    //1、一个变量声明了,但是没有赋值,值默认为undefined
    var b;
    console.log(b);//b就是一个undefined类型的值

    //2、一个变量声明了,并且赋值了一个undefined的值
    var c=undefined;
    console.log(c);//c也是一个undefined类型的值

    //3、一个对象中,获取某个不存在的属性,值也是undefined
    var d={};
    console.log(d.age);//由于d对象没有age属性,值:undefined

对象的基本使用

    //1、创建对象
    var person={
        gender:"男",
        height:185,
        toShanghai:function(){
            console.log('做着高端大气上档次的和谐号动车组');
        }
    };
    //2、获取属性
    console.log(person.gender);         //"男"
    console.log(person["height"]);      //185
    
    //3、设置属性
    person.address="上海市闸北区";
    person.height=190;
    
    //4、删除属性
    delete person.gender;
    delete person.a;        //这段代码没有意义,也不会报错

    //delete关键字只能删除对象中的属性,不能删除变量
    // var a=100;
    // delete a;//错误的理解

    //清空对象
    person={};      //person对象不再具有任何属性

    person=null;    
    //表示将person变量的值赋为null,从此以后person不再是一个对象了

构造函数、实例

    //1、
    function _fn(){
        return 5;
    }
    var s=new _fn();
    //s是_fn构造函数的实例

    //2、
    function _fn3(){}
    var q1=new _fn3();
    //q1是_fn3构造函数的实例

    //3、
    function fn3(){
        return [1,3,5]; 
    }
    var qw=new fn3();//qw=[1,3,5]
    console.log(qw);
    //qw不是fn3构造函数的实例

    //如何判断一个数据是否是复杂数据类型?
    //使用排除法:
    //a、看它的值是不是:数字、字符串、布尔值、null、undefined,
    //b、如果不是以上5种值,那就是复杂数据类型

    //  举例:
    // [1,3,5]
    //  /abc/
    //  function(){}
    //  new Object();


    //为什么要理解构造函数的返回值?
    //String是一个内置函数
    //a、String()
    //b、new String()
    
    //结论:一个函数通过new调用,或者不通过new调用,很多时候会有截然不同的返回值

    //我如何分辨出一个对象到底是不是某个构造函数的实例?
    //a、var isTrue=xxx instanceof Person

    function Person(){

    }
    var p1=new Person();
    console.log(p1 instanceof Person);//true,就是Person的实例

    function Student(){
        return 100;
    }
    var s1=new Student();
    console.log(s1 instanceof Student);//true,就是Student的实例

    function Programmer(){
        return [1,3,5]
    }
    var pro=new Programmer();//pro并不是Programmer的实例
    console.log(pro instanceof Programmer);//false
    
    console.log("是数组的实例吗?",pro instanceof Array);//true

    //小技巧:如何通过肉眼识别xxx对象是哪个构造函数的实例?
    //xxx.__proto__属性,也是对象,该对象中一般都会有一个constructor属性,这个指向PPP函数,那么就可以认为:xxx是PPP构造函数的实例


    //typeof运算符,只能判断:数字、字符串、布尔值、undefined、函数

    //切记:千万不能使用typeof运算符来判断对象的构造函数

    //typeof null === "object"
    //typeof {}  === "object"
    //typeof []  === "object"
    //typeof function(){} === "function"
    //typeof /abc/     === "object"

原型对象

    function Person(name,age){
        this.name=name;
        this.age=age;
        this.say=function(){}
    }
    var p1=new Person();
    var p2=new Person();
    
    //p1对象和p2对象的say方法是否是同一个方法:false
    console.log(p1.say===p2.say);

    //由于say方法可能功能相似,但是不是同一个方法(没有指向同一块内存,会造成内存浪费)
    //解决方案:把say方法写在他们共同的(父对象)中
    //其实他们共同的父对象,就可以通过:Person.prototype来获取

    //-->只要把say方法写在Person.prototype中,那么say方法就是同一个方法
    Person.prototype.run=function(){
        console.log('时速500KM');
    }
    //此时p1和p2都可以访问到run方法
    p1.run();
    p2.run();
    //验证p1.run和p2.run是否是同一个方法?
    console.log(p1.run == p2.run); //指向同一个方法,这种方法避免了内存的浪费
    
    console.log(p1.run == Person.prototype.run);
    //true

    var p3=new Person();
    console.log(p3.run == p1.run); //true
    console.log(p3.run === p1.run);//true
    //结论:只要往某个构造函数的prototype对象中添加某个属性、方法,那么这样的属性、方法都可以被所有的构造函数的实例所共享
    //==>这里的【构造函数的prototype对象】称之为原型对象
    //  Person.prototype是 p1 p2 p3 的原型对象
    //  Person.prototype是Person构造函数的【实例】的原型对象

    //猜猜看?
    //  Person的原型对象是谁呢?
    //  -->首先要知道Person的构造函数:-->Function
    //  -->所以Person的原型对象是:Function.prototype

    //  p1的原型对象是谁呢?
    //  -->首先要知道p1是谁创建的?    -->Person
    //  -->所以p1的原型对象时:     Person.prototype

继承方式1:原型链继承

    function Person(){}
    Person.prototype={
        constructor:Person,
        say:function(){
            console.log("你好");
        },
        run:function(){
            console.log("正在进行百米冲刺");
        }
    }
    var p1=new Person();
    var p2=new Person();
    console.log(p1.say === p2.say);   //true
// 注意点:
// a、一般情况下,应该先改变原型对象,再创建对象
// b、一般情况下,对于新原型,会添加一个constructor属性,从而不破坏原有的原型对象的结构

继承方式2:拷贝继承

场景:有时候想使用某个对象中的属性,但是又不能直接修改它,于是就可以创建一个该对象的拷贝

    //1、已经拥有了o3对象
    var o3={gender:"男",grade:"初三",group:"第五组",name:"张三"};
    //2、创建一个o3对象的拷贝(克隆):for...in循环
    var o4={};
        //a、取出o3对象中的每一个属性
    for (var key in o3) {
                //key就是o3对象中的每一个属性
        //b、获取到对应的属性值
        var value = o3[key];
        //c、把属性值放到o4中
        o4[key] = value;
    }

    //3、修改克隆对象,把该对象的name属性改为"李四"
    o4.name="李四"
    console.log(o4);    //最终的目标对象的结果

    //后续如果修改了o4对象中的相关属性,就不会影响到o3

扩展:es6中有了 <对象扩展运算符> 仿佛就是专门为了拷贝继承而生:
    - 优点:简单的令人发指

var source={name:"李白",age:15}
    //让target是一个新对象,同时拥有了name、age属性
    var target={ ...source }
    
    var target2={ ...source,age:18 }

继承方式3:原型式继承

- a、创建一个纯洁的对象:对象什么属性都没有
- b、创建一个继承自某个父对象的子对象

var parent={ age:18,gender:"男"};
var student=Object.create(parent);
//student.__proto__===parent

继承方式4:借用构造函数继承

+ 场景:适用于2种构造函数之间逻辑有相似的情况
+ 原理:函数的call、apply调用方式

+ 局限性:Animal(父类构造函数)的代码必须完全适用于Person(子类构造函数)

function Animal(name,age){
    this.name=name;
    this.age=age;
}
function Person(name,age,address){
    Animal.call(this,name,age);
    // 或者Animal.apply(this, [name,age])
    this.address=address;
}

继承方式5:寄生继承、寄生组合继承

+ 概念:JS里面的对象可能会有父对象,父对象还会有父对象,。。。。。祖先
+ 根本:继承
    - 属性:对象中几乎都会有一个__proto__属性,指向他的父对象
        -意义:可以实现让该对象访问到父对象中相关属性
+ 根对象:Object.prototype
    - var arr=[1,3,5]
    - arr.__proto__:Array.prototype
    - arr.__proto__.__proto__找到了根对象

        function Animal(){}
        var cat=new Animal();
        //cat.__proto__:Animal.prototype
        //cat.__proto__.__proto__:根对象

ES6中的面向对象写法

    class Person{
      // 构造函数
      constructor (name,age) {
        this.name = name
        this.age = age
      }
      // 静态方法
      static maxAge (name) {
        if (name >= 120) {
          console.log('年龄不能超过120')
        }
      }
      // 实例方法
      travel () {
        console.log(`${this.name}去了浪漫的土耳其`)
      }
    }

    // 继承
    class Student extends Person{
      constructor (name,age) {
        super(name,age)
      }
    }
    let s1 = new Student('小明',15)
    Person.maxAge(125)
    s1.travel()


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值