面向对象

javascript面向对象

一. 什么是对象?

面向对象编程(Object Oriented Programing,缩写为OOP)是目前主流的编程范式,它将真实世界各种复杂的关系,抽象为一个个的对象,然后由对象之间的分工与合作,完成真实世界的虚拟。

每一个对象都是功能中心,具有明确的分工,可以完成接受信息,处理数据,发出信息等任务,因此面向对象编程具有灵活,代码可复用,高度模块化等特点。容易维护和开发比起由一系列函数或指令组成的传统的过程式编程(procedura programming),更适合多人合作的大型项目。

那么面向对象(object)到底是什么?
1. 对象是单个实物的抽象。
一本书、一个人、一辆车都可以是对象。
一个数据库、一张网页、一个服务器甚至与服务器的连接也可以是对象。
当实物抽象成对象,实物之间的关系就变成了对象之间的关系,从而就可以模拟现实情况,针对对象进行编程。

  1. 对象是一个容器,封装了属性(property)和方法(method)。
    属性是对象的状态,方法是对象的行为(完成某种任务)。比如我么可以把动物抽象为一个animal对象,使用属性记录具体是哪种动物。使用方法来表示动物的某种行为(奔跑、捕猎、休息等)。

二、构造函数

面向对象的第一步,就是要生成对象。
前面说过,对象是单个实物的抽象,通常需要一个的模板,表示某一类实物的共同特征,然后对象根据这个模板生成。

经典的面向对象编程语言(比如java和C++),存在“类”(class)这个概念。所谓“类”就是对象的模板。它提供模板,描述对象的基本结构。一个构造函数可以生成多个对象,这些对象都具有相同的结构。

构造函数的写法就是一个普通函数,但是有自己的特征和用法

    var Vehicle = function(){
        this.price = 100;
    };
    // 函数三种创建方法:function fun_name(){}; var = function(){}; new function();

上面代码中,Vehicle就是一个构造函数,它提供模板,用来生成实例对象,为了与普通函数区别,构造函数名字的第一个字母通常大写。

特征: 函数体内部使用了this关键字,代表所要生成对象实例.
用法: 生成对象的时候,必须用new命令,调用Vehicle函数.

三、new命令

  1. 基本用法
    new命令的作用,就是用来执行构造函数,返回一个实例对象。
    var Vehicle = function(){
        this.price = 100;
    };
    var v = new Vehicle();
    v.price //100

上面代码通过new命令,让构造函数Vehicle生成一个实例对象,保存在变量v中,这个新生成的实例对象,从构造函数vehicle中继承了price属性,new命令执行时,构造函数内部的this,就、代表了新生成的实例对象,this.price表示实例对象有一个price属性,值是100.

使用new命令时,根据需要,构造函数也可以接受参数

    var Vehicle = function(p){
        this.price = p;
    };
    var v = new Vehicle(300);

new命令本身可以执行构造函数,所以后面的构造函数可以带括号也可以不带括号.

var v = new Vehicle();
var v = new Vehicle;

以上代码是等价的。

一个问题,如果你忘记使用new命令,直接调用构造函数会发生什么?
这种情况下,构造函数就变成普通函数,并不会生成实例对象,而且由于后面说的原因,this这个时候代表全局对象。造成一些意想不到的结果。

    var Vehicle = function(){
        this.price = 100;   //this指向全局对象,浏览器下是window。
    };
    var v = Vehicle();
    v.price //报错
    price   //100

上面的代码中,调用vehicle构造函数,忘了加上new命令,结果,price属性变成了全局变量,而变量v的值变成undefined。(因为Vehicle没有返回值)

因此,应该非常小心,避免出现不使用new命令,直接调用构造函数的情况,为了保证构造函数必须和new命令一起使用。一个解决办法是,在构造函数的内部使用严格模式,就是在第一行加上“use strict”。(严格模式下JavaScript不允许对undefined添加属性)

function Fubar(foo,bar){
    'use strict';
    this._foo=foo;
    this._bar=bar;
}
Fubar();

上面代码Fubar为构造函数。use strict命令保证了该函数在严格模式下运行,由于严格模式中,函数内部的this不能指向全局对象,默认等于undefined,导致不加new调用时会报错(严格模式下,Javascript不允许对undefined添加属性)

另外一种解决方法,是在构造函数内部判断是否使用new、命令,如果发现没有new,则返回一个实例对象

function Fubar(foo,bar){
    if(!(this instanceof Fubar)){
        return new Fubar(foo,bar);
    }
    this._foo = foo;
    this._bar = bar;
}
Fubar(1,2).foo
(new Fubar(1,2)).foo

在上面代码中的构造函数,不管加不加new命令,都可以获得一个新的对象。

  1. new命令的原理
    使用new命令时,他后面的函数调用就不是正常调用,而是依次执行下面的步骤
    • 创建一个空对象,作为要返回的实例对象
    • 将这个对象的原型,指向构造函数的prototype属性
    • 将这个空对象赋值给函数内部的this关键字
    • 开始执行构造函数内部的代码

也就是说构造函数内部,this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。构造函数之所以叫“构造函数”,就是说这个函数的目的,就是操作一个空对象(this对象),将其“构造”为所需要的样子。

如果构造函数内有return语句,而且return后面跟着一个对象,new命令将会返回return语句指定的对象:否则不管return语句,返回this对象。

但是,如果return语句返回的是一个跟this无关的对象,new命令会返回这个新对象,而不是this对象。

如果普通函数(函数内部没有this关键字)使用new命令,则会返回一个空对象。

new命令简化的内部流程, 下面的代码表示

function _new(constructor/*构造函数*/,parmal/*构造函数参数*/){

    var args = [].slice.call(arguements);
    //将argumenets转换成数组

    var constructor = args.shift();
    //取出构造函数

    var context = Object.create(constructor.prototype);
    // 创建一个空对象,继承构造函数的prototype属性

    var result = constructor.apply(context,args);

    // 返回结果如果是对象,就直接返回,否则返回context对象
    return (typeof result === "object"&& result != null) ? result : context ;

}
  1. new.target
    函数内部可以使用new.target属性。如果,当前函数是new命令调用的,new.target指向当前函数,否则指向undefined。
function fn(){
    console.log(new.target === fn);
}
function fn(a){
    if(!new.target){
        throw new Error('请使用new操作符调用!');
    }
    this.a = a;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值