javascript面向对象那些事

什么是面向对象

面向对象就是说,使用对象的时候,你可以直接使用它所提供的功能而忽略其内部组成情况。比如说,你家里的电视机,你使用了遥控,就能操作电视机,但是你实际上不知道这台电视机里面是什么零件组成的,你只要知道,我拿到遥控就可以操作电视机就好了。这就是一种面向对象的思想。

面向对象和面向过程的区别

面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。
面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。

面向对象的特征

  1. 封装性
    封装指的是隐藏内部的实现细节,只对外开放操作接口。接口就是对象的方法,无论对象的内部多么复杂,用户只需知道这些接口怎么使用即可。
  2. 继承性
    继承是指个对象继承另一个对象的成员, 从而在不改变另一 个对象的前提下进行扩展
  3. 多态性
    多态指的是同一个操作作用于不同的对象,会产生不同的执行结果。实际上JavaScript被设计成一种弱类型语言(即一个变量可以存储任意类型的数据),就是多态性的体现。例如,数字、数组、函数都有toString()方法,当使用不同的对象调用该方法时,执行结果不同,示例代码如下:
    var obj=123;
    console.log(obj.toString());//输出结果:123
    obj=[1,2,3];
    console.log(obj.toString());//输出结果:1,2,3
    obj=funcation(){};
    console.log(obj.toString());//输出结果:funcation(){}

JavaScript 定义了 5 种原始数据类型:

string
number
boolean
null
undefined

对象定义的两种方式

1.字面量的方式进行定义

    var  person = {
            name: "Tom ",
            sex: " man",
            age:19,
            run:function(){
                console.log("一天跑一公里");
            }
    }

2.使用 {} 进行定义

    var  person = {};
         person.name = "Tom ";
         person.sex = " man";
         person.age = 19;
         person.run = function(){
            console.log("一天跑一公里");
         }

JavaScript 对象构造器

    function Person(first, last, age, eye) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
        this.eyeColor = eye;
    }

用大写首字母对构造器函数命名,以上函数 Person() 就是对象构造器函数
通过 new 关键词调用构造器函数可以创建相同类型的对象:

    var myFather = new Person("Bill", "Gates", 62, "blue");
    var myMother = new Person("Steve", "Jobs", 56, "green");

使用 prototype 属性

JavaScript prototype 属性允许您为对象构造器添加新属性:

    function Person(first, last, age, eyecolor) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
        this.eyeColor = eyecolor;
    }
    Person.prototype.nationality = "English";

JavaScript prototype 属性也允许您为对象构造器添加新方法

    function Person(first, last, age, eyecolor) {
        this.firstName = first;
        this.lastName = last;
        this.age = age;
        this.eyeColor = eyecolor;
    }
    Person.prototype.name = function() {
        return this.firstName + " " + this.lastName;
    };

JavaScript 对象方法

    // 添加或更改对象属性
    Object.defineProperty(object, property, descriptor)
    // 以数组返回所有可枚举的属性
    Object.keys(object)
    // 以数组返回所有属性
    Object.getOwnPropertyNames(object)

JavaScript 对象原型

原型继承

原型继承:每一个构造函数都有prototype原型属性,通过构造函数创建出来的对象都继承自该原型属性。所以可以通过更改构造函数的原型属性来实现继承。
JavaScript 对象都从原型继承属性和方法
日期对象继承自 Date.prototype。数组对象继承自 Array.prototype。Person 对象继承自 Person.prototype
Object.prototype 位于原型继承链的顶端
日期对象、数组对象和 Person 对象都继承自 Object.prototype

1.简单混入继承
直接遍历一个对象,将所有的属性和方法加到另一对象上

    var  person = {
            name: "Tom ",
            sex: " man",
            age:19,
            run:function(){
                console.log("一天跑一公里");
            }
    }
    var child =  {};
    for (var k in person){
        child[k] = person[k]
    }
    console.log(child)//打印的对象和person一样

2.混入式原型继承
混入式原型继承其实与上面的方法类似,只不过是将遍历的对象添加到构造函数的原型上。

    var  person = {
        name: "Tom ",
        sex: " man",
        age:19,
        run:function(){
            console.log("一天跑一公里");
        }
    }
    function Child(){
        this.weight = 50;
    }
    for (var k in person){
        Child.prototype[k]= person[k]
    }
    var p1 = new Child();
    var p2 = new Child();
    var p3 = new Child();
    console.log(p1.name)//Tom
    console.log(p2.sex)//man
    console.log(p3.age)//19

面向对象思想封装一个原型继承
可以利用面向对象的思想,将面向过程进行封装。

    function Child(){
        this.weight = 50;
    }
    //给构造函数Child添加一个方法 extend
    Child.prototype.extend = function (obj){
        for (var k in obj){
            this[k]= obj[k]
        }
    }
    //调用 extend 方法
    Child.prototype.extend({
        name: "Tom ",
        sex: " man",
        age:19,
        run:function(){
            console.log("一天跑一公里");
        }
    })

3.替换式原型继承
替换式原型继承,其实就是将一个构造函数的原型对象替换成另一个对象。

    function Child(){
        this.weight = 50;
    }
    var person = {
        name: "Tom ",
        sex: " man",
        age:19,
        run:function(){
            console.log("一天跑一公里");
        }
    }
    Child.prototype = person
    var p1 = new Child();
    var p2 = new Child();
    var p3 = new Child();
    console.log(p1.name)//Tom
    console.log(p2.sex)//man
    console.log(p3.age)//19

这样做会产生一个问题,就是替换的对象会重新开辟一个新的空间。替换原型对象的方式会导致原型的constructor的丢失,constructor属性是默认原型对象指向构造函数的,就算是替换了默认原型对象,这个属性依旧是默认原型对象指向构造函数的,所以新的原型对象是没有这个属性的。
解决方法:手动关联一个constructor属性

    function Child(){
        this.weight = 50;
    }
    var person = {
        name: "Tom ",
        sex: " man",
        age:19,
        run:function(){
            console.log("一天跑一公里");
        }
    }
    //给需要替换的对象添加一个 constructor 属性 指向原本的构造函数
    person.constructor = Child;
    //将一个构造函数的原型对象替换成另一个对象
    Child.prototype = person;
    var p1 = new Child();
    console.log(p1.__proto__.constructor === Child)//true

4.Object.create()方法实现原型继承
当我们想把对象1作为对象2的原型的时候,就可以实现对象2继承对象1。前面我们了解了一个属性:proto,实例出来的对象可以通过这个属性访问到它的原型,但是这个属性只适合开发调试时使用,并不能直接去替换原型对象。所以这里介绍一个新的方法:Object.create()。
语法:
var obj1 = Object.create(原型对象);示例代码: 让空对象obj1继承对象obj的属性和方法

    var person = {
        name: "Tom ",
        sex: " man",
        age:19,
        run:function(){
            console.log("一天跑一公里");
        }
    }
    var abj1 = Object.create(person)
    console.log(abj1.name)//Tom
    abj1.run()//一天跑一公里

兼容性:
由于这个属性是ECMAScript5的时候提出来的,所以存在兼容性问题。
利用浏览器的能力检测,如果存在Object.create则使用,如果不存在的话,就创建构造函数来实现原型继承。

    function create(person){
        if(Object.create){
            return Object.create(person);
        }else{
            function Fun(){}
            Fun.prototype = person
            return new Fun();
        }
    }
    var person = {
        name: "Tom ",
        sex: " man",
        age:19,
        run:function(){
            console.log("一天跑一公里");
        }
    }
    var abj1  = create(person)
    console.log(abj1.name)//Tom
    abj1.run()//一天跑一公里

call()/apply()方法

    function Teacher(name,age){
        this.name = name;
        this.age = age;
        this.sayhi = function(){
            console.log('name:'+name+", age:"+age);
        }
    }
    function Student(){
        var args = arguments;
        Teacher.call(this,args[0],args[1]);
        // Teacher.apply(this,arguments);
    }
    var teacher1 = new Teacher('xiaoming',23);
    teacher1.sayhi();

    var student1 = new Student('xiaolan',12);
    student1.sayhi();

    // console.log: name:xiaoming, age:23
    // console.log: name:xiaolan, age:12

 上一篇
javascript相关程序计算 javascript相关程序计算
判断一个字符串中出现次数最多的字符,统计这个次数 var str = '121232jddsds232322222dffrrrrr'; var json = {}; for (var i = 0; i < st
2020-01-17
下一篇 
常用git命令 常用git命令
其他操作 git init:初始化本地库 git status:查看工作区、暂存区的状态 git add <file name>:将工作区的“新建/修改”添加到暂存区 git rm --cached <file name&
2020-01-13
  目录