面向对象的三大基本特性

封装(把相关的信息(无论数据或方法)存储在对象中的能力)

继承(由另一个类(或多个类)得来类的属性和方法的能力)

多态(一个对象在不同情况下的多种形态)

定义类或对象

第一种:基于Object对象

var person = new Object();
person.name = "Rose";
person.age = 18;
person.getName = function () {
    return this.name;
};
console.log(person.name);//Rose
console.log(person.getName);//function () {return
this.name;}
console.log(person.getName());//Rose

缺点:不能创建多个对象。

第二种:基于字面量方式

var person = {
    name : "Rose",
    age : 18 ,
    getName : function () {
        return this.name;
    }
};
console.log(person.name);//Rose
console.log(person.getName);//function () {return
this.name;}
console.log(person.getName());//Rose

优点:比较清楚的查找对象包含的属性和方法;

缺点:不能创建多个对象。

第三种:工厂模式

方式一:

function createPerson(name,age) {
    var object = new Object();
    object.name = name;
    object.age = age;
    object.getName = function ()
{
        return this.name;
    };
    return object;
}
var person1 = createPerson("Rose",18);
var person2 = createPerson("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//false//重复生成函数,为每个对象都创建独立的函数版本

优点:可以创建多个对象;

缺点:重复生成函数getName(),为每个对象都创建独立的函数版本。

方式二:

function createPerson(name,age) {
    var object = new Object();
    object.name = name;
    object.age = age;
    object.getName = getName;
    return object;
}
function getName() {
    return this.name;
}
var person1 = createPerson("Rose",18);
var person2 = createPerson("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享同一个函数

优点:可以创建多个对象;

缺点:从语义上讲,函数getName()不太像是Person对象的方法,辨识度不高。

第四种:构造函数方式

方式一:

function Person(name,age) {
    this.name = name;
    this.age = age;
    this.getName = function ()
{
        return this.name;
    }
}
var person1 = new Person("Rose",18);
var person2 = new Person("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName); //false//重复生成函数,为每个对象都创建独立的函数版本

优点:可以创建多个对象;

缺点:重复生成函数getName(),为每个对象都创建独立的函数版本。

方式二:

function Person(name,age) {
    this.name = name;
    this.age = age;
    this.getName = getName
;
}
function getName() {
    return this.name;
}
var person1 = new Person("Rose",18);
var person2 = new Person("Jack",20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName); //true//共享同一个函数

优点:可以创建多个对象;

缺点:从语义上讲,函数getName()不太像是Person对象的方法,辨识度不高。

第五种:原型方式

function Person() {
}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.getName = function () {
    return this.name;
};
var person1 = new Person();
var person2 = new Person();
console.log(person1.name);//Rose
console.log(person2.name);//Rose//共享同一个属性
console.log(person1.getName
=== person2.getName);//true//共享同一个函数

缺点:它省略了为构造函数传递初始化参数,这在一定程序带来不便;另外,最主要是当对象的属性是引用类型时,它的值是不变的,总是引用同一个外部对象,所有实例对该对象的操作都会影响其它实例:

function Person() {
}
Person.prototype.name = 'Rose';
Person.prototype.age = 18;
Person.prototype.lessons = ["语文","数学"];
Person.prototype.getName = function () {
    return this.name;
};
var person1 = new Person();
person1.lessons.push("英语");
var person2 = new Person();
console.log(person1.lessons);//["语文", "数学", "英语"]
console.log(person2.lessons);//["语文", "数学", "英语"]//person1修改影响了person2

第六种:构造函数+原型方式(推荐)

function Person(name,age) {
    this.name = name;
    this.age = age;
}
Person.prototype.getName = function () {
    return this.name;
};
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定义的方法

缺点:属性定义在构造函数内,方法定义在构造函数外,与面向对象的封装思想不符。

第七种:构造函数+动态原型方式(推荐)

方式一:

function Person(name,age) {
    this.name = name;
    this.age = age;
    if (typeof
Person._getName === "undefined"){
        Person.prototype.getName
= function () {
            return this.name;
        };
        Person._getName = true;
    }
}
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定义的方法

方式二:

function Person(name,age) {
    this.name = name;
    this.age = age;
    if (typeof
this.getName !== "function"){
        Person.prototype.getName
= function () {
            return this.name;
        };
    }
}
var person1 = new Person('Rose', 18);
var person2 = new Person('Jack', 20);
console.log(person1.name);//Rose
console.log(person2.name);//Jack
console.log(person1.getName === person2.getName);//true//共享原型中定义的方法

对象属性的扩展及删除

Javascript的对象可以使用 ’.’ 操作符动态的扩展其属性,可以使用 ’delete’ 关键字或将属性的值设置为
’undefined’ 来删除属性。

function Person(name,age) {
    this.name = name;
    this.age = age;
    if (typeof Person._getName
=== "undefined"){
        Person.prototype.getName
= function () {
            return this.name;
        };
        Person._getName =
true;
    }
}
var person = new Person("Rose",18);
person.job
= 'Engineer';//添加属性
console.log(person.job);//Engineer
delete person.job;//删除属性
console.log(person.job);//undefined//删除属性后值为undefined
person
.age = undefined;//删除属性
console.log(person.age);//undefined//删除属性后值为undefined

对象属性类型

数据属性

特性:

[configurable]:表示能否使用delete操作符删除从而重新定义,或能否修改为访问器属性。默认为true;

[enumberable]:表示是否可通过for-in循环返回属性。默认true;

[writable]:表示是否可修改属性的值。默认true;

[value]:包含该属性的数据值。读取/写入都是该值。默认为undefined;如上面实例对象person中定义了name属性,其值为’My
name’,对该值的修改都反正在这个位置

function Person(name,age) {
    this.name = name;
    this.age = age;
    if (typeof Person._getName
=== "undefined"){
        Person.prototype.getName
= function () {
            return this.name;
        };
        Person._getName =
true;
    }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"name",{configurable:false,writable:false});
person.name
= "Jack";
console.log(person.name);//Rose//重新赋值无效
delete person.name;
console.log(person.name);//Rose//删除无效

注意:

一旦将configurable设置为false,则无法再使用defineProperty将其修改为true(执行会报错:cannot redefine property : propertyName)

function Person(name,age) {
    this.name = name;
    this.age = age;
    if (typeof Person._getName
=== "undefined"){
        Person.prototype.getName
= function () {
            return this.name;
        };
        Person._getName =
true;
    }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"name",{configurable:false,writable:false});
person.name = "Jack";
console.log(person.name);//Rose//重新赋值无效
delete person.name;
console.log(person.name);//Rose//删除无效
Object.defineProperty(person,"name",{configurable:true,writable:true});//Cannot
redefine property: name

访问器属性

特性:

[configurable]:是否可通过delete操作符删除重新定义属性;

[numberable]:是否可通过for-in循环查找该属性;

[get]:读取属性时调用,默认:undefined;

[set]:写入属性时调用,默认:undefined;

访问器属性不能直接定义,必须使用defineProperty()或defineProperties来定义:如下

function Person(name,age) {
    this.name = name;
    this._age = age;
    if (typeof Person._getName
=== "undefined"){
        Person.prototype.getName
= function () {
            return this.name;
        };
        Person._getName =
true;
    }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"age",{
    get:function () {
        return this._age;
    },
    set:function (age) {
        this._age = age;
    }});
person.age = 20;
console.log(person.age);//20//person.age=20是使用set方法将20赋值给_age,person.age是使用get方法将_age的读取出来
console.log(person._age);//20

获取所有的属性和属性的特性

使用Object.getOwnPropertyNames(object)方法可以获取所有的属性;

使用Object.getOwnPropertyDescriptor(object,property)方法可以取得给定属性的特性;

function Person(name,age) {
    this.name = name;
    this._age = age;
    if (typeof Person._getName
=== "undefined"){
        Person.prototype.getName
= function () {
            return this.name;
        };
        Person._getName =
true;
    }
}
var person = new Person("Rose",18);
Object.defineProperty(person,"age",{
    get:function () {
        return this._age;
    },
    set:function (age) {
        this._age = age;
    }});
console.log(Object.getOwnPropertyNames(person));//["name",
"_age", "age"]
console.log(Object.getOwnPropertyDescriptor(person,"age"));//{enumerable:
false, configurable: false, get: function, set: function}

对于数据属性,可以取得:configurable,enumberable,writable和value;

对于访问器属性,可以取得:configurable,enumberable,get和set;

继承机制实现

对象冒充

function Father(name) {
    this.name = name ;
    this.getName = function ()
{
        return this.name;
    }
}
function Son(name,age) {
    this._newMethod = Father;
    this._newMethod(name);
    delete  this._newMethod;

this.age = age;
    this.getAge = function ()
{
        return this.age;
    }
}
var father = new Father("Tom");
var son = new Son("Jack",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类getName()方法
console.log(son.getAge());//18

多继承(利用对象冒充可以实现多继承)

function FatherA(name) {
    this.name = name ;
    this.getName = function ()
{
        return this.name;
    }
}
function FatherB(job) {
    this.job = job;
    this.getJob = function ()
{
        return this.job;
    }
}
function Son(name,job,age) {
    this._newMethod = FatherA;
    this._newMethod(name);
    delete  this._newMethod;
    this._newMethod = FatherB;
    this._newMethod(job);
    delete  this._newMethod;

this.age = age;
    this.getAge = function ()
{
        return this.age;
    }
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//继承父类FatherA的getName()方法
console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法
console.log(son.getAge());//18

call()方法

function Father(name) {
    this.name = name ;
    this.getName = function ()
{
        return this.name;
    }
}
function Son(name,job,age) {
    Father.call(this,name);

this.age = age;
    this.getAge = function ()
{
        return this.age;
    }
}
var father = new Father("Tom");
var son = new Son("Jack","Programmer",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类getName()方法
console.log(son.getAge());//18

多继承(利用call()方法实现多继承)

function FatherA(name) {
    this.name = name ;
    this.getName = function ()
{
        return this.name;
    }
}
function FatherB(job) {
    this.job = job;
    this.getJob = function ()
{
        return this.job;
    }
}
function Son(name,job,age) {
    FatherA.call(this,name);
    FatherB.call(this,job);

this.age = age;
    this.getAge = function ()
{
        return this.age;
    }
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//继承父类FatherA的getName()方法
console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法
console.log(son.getAge());//18

apply()方法

function Father(name) {
    this.name = name ;
    this.getName = function ()
{
        return this.name;
    }
}
function Son(name,job,age) {
    Father.apply(this,new Array(name));

this.age = age;
    this.getAge = function ()
{
        return this.age;
    }
}
var father = new Father("Tom");
var son = new Son("Jack","Programmer",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类getName()方法
console.log(son.getAge());//18

多继承(利用apply()方法实现多继承)

function FatherA(name) {
    this.name = name ;
    this.getName = function ()
{
        return this.name;
    }
}
function FatherB(job) {
    this.job = job;
    this.getJob = function ()
{
        return this.job;
    }
}
function Son(name,job,age) {
    FatherA.apply(this,new Array(name));
    FatherB.apply(this,new
Array(job));

this.age = age;
    this.getAge = function ()
{
        return this.age;
    }
}
var fatherA = new FatherA("Tom");
var fatherB = new FatherB("Engineer");
var son = new Son("Jack","Programmer",18);
console.log(fatherA.getName());//Tom
console.log(fatherB.getJob());//Engineer
console.log(son.getName());//Jack//继承父类FatherA的getName()方法
console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法
console.log(son.getAge());//18

原型链方法

function Father() {
}
Father.prototype.name = "Tom";
Father.prototype.getName = function () {
  return this.name;
};
function Son() {
}
Son.prototype
= new Father();
Son.prototype.age = 18;
Son.prototype.getAge = function () {
    return this.age;
};
var father = new Father();
var son = new Son();
console.log(father.getName());//Tom
console.log(son.getName());//Tom//继承父类FatherA的getName()方法
console.log(son.getAge());//18

混合方式(call()+原型链)

function Father(name) {
    this.name = name;
}
Father.prototype.getName = function () {
  return this.name;
};
function Son(name,age) {
    Father.call(this,name);
    this.age = age;
}
Son.prototype
= new Father();
Son.prototype.getAge = function () {
    return this.age;
};
var father = new Father("Tom");
var son = new Son("Jack",18);
console.log(father.getName());//Tom
console.log(son.getName());//Jack//继承父类Father的getName()方法
console.log(son.getAge());//18

多态机制实现

function Person(name) {
    this.name = name;
    if (typeof this.getName
!== "function"){
        Person.prototype.getName
= function () {
            return this.name;
        }
    }
    if (typeof this.toEat
!== "function"){
        Person.prototype.toEat
= function (animal) {
            console.log( this.getName()
+ "说去吃饭:");
            animal.eat();
        }
    }
}
function Animal(name) {
    this.name = name;
    if (typeof this.getName
!== "function"){
        Animal.prototype.getName
= function () {
            return this.name;
        }
    }
}
function Cat(name) {
    Animal.call(this,name);
    if (typeof this.eat
!== "function"){
        Cat.prototype.eat
= function () {
            console.log(this.getName()
+ "吃鱼");
        }
    }
}
Cat.prototype = new Animal();
function Dog(name) {
    Animal.call(this,name);
    if (typeof this.eat
!== "function"){
        Dog.prototype.eat
= function () {
            console.log(this.getName()
+ "啃骨头");
        }
    }
}
Dog.prototype = new Animal();

var person = new Person("Tom");
person.toEat(new Cat("cat"));//Tom说去吃饭:cat吃鱼
person
.toEat(new Dog("dog"));//Tom说去吃饭:dog啃骨头

浅谈javascript的面向对象思想的更多相关文章

  1. 浅谈JavaScript的面向对象和它的封装、继承、多态

    写在前面 既然是浅谈,就不会从原理上深度分析,只是帮助我们更好地理解... 面向对象与面向过程 面向对象和面向过程是两种不同的编程思想,刚开始接触编程的时候,我们大都是从面向过程起步的,毕竟像我一样, ...

  2. 浅谈JavaScript的面向对象程序设计(四)

    本文继续讲解JavaScript的面向对象程序设计.继承是面向对象语言中的一个基本概念,面向对象语言支持两种继承实现方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.但是在 ...

  3. 浅谈JavaScript的面向对象程序设计(三)

    前面已经对JavaScript的面向对象程序设计作了简单的介绍,包括了对象的属性.对象的工厂模式.构造函数和原型等.通过介绍,这些创建对象的方法依然有不少优化和改进的地方. 组合使用构造函数模式和原型 ...

  4. 浅谈JavaScript的面向对象程序设计(一)

    面向对象的语言有一个标志,他们都有类的概念,通过类可以创建多个具有相同属性和方法的对象.但是JavaScript中没有类的概念,因此JavaScript与其他的面向对象语言还是有一定区别的.JavaS ...

  5. 浅谈JavaScript的面向对象程序设计(二)

    前面介绍通过Object构造函数或者字面量创建单个对象,但是通过这个的方法创建对象有明显的缺点:调用同一个接口创建多个实例,会产生大量的重复代码.怎么样解决? 工厂模式 工厂模式是软件工程领域经常使用 ...

  6. 浅谈javascript函数节流

    浅谈javascript函数节流 什么是函数节流? 函数节流简单的来说就是不想让该函数在很短的时间内连续被调用,比如我们最常见的是窗口缩放的时候,经常会执行一些其他的操作函数,比如发一个ajax请求等 ...

  7. 浅谈JavaScript浮点数及其运算

    原文:浅谈JavaScript浮点数及其运算     JavaScript 只有一种数字类型 Number,而且在Javascript中所有的数字都是以IEEE-754标准格式表示的.浮点数的精度问题 ...

  8. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

  9. 浅谈 JavaScript 编程语言的编码规范

    对于熟悉 C/C++ 或 Java 语言的工程师来说,JavaScript 显得灵活,简单易懂,对代码的格式的要求也相对松散.很容易学习,并运用到自己的代码中.也正因为这样,JavaScript 的编 ...

随机推荐

  1. 获取 Windows Phone 的 User-Agent 字符串

    这个是简单介绍一下如何在wp开发中获取 Windows Phone 的 User-Agent 字符串,更多wp移动开发就去那个wp教程网吧.http://wp.662p.com 使用方法 public ...

  2. 应用三:Vue之混入(mixin)与全局混入

    (注:本文适用于有一定Vue基础或开发经验的读者,文章就知识点的讲解不一定全面,但却是开发过程中很实用的) 首先介绍一下混入mixin的概念:   官方文档:混入提供了一种非常灵活的方式,来分发 Vu ...

  3. 创建一个dynamics CRM workflow (三) - Creating Configuration Entity for Custom Workflow

    上个帖子中, 我们创建了个发email的workflow. 但是我们邮件当中的tax 值是 hard code, 这在开发当中是不容许的. 那今天我们来把这个build in workflow用 in ...

  4. MongoDB_pymongo

    python使用pymongo访问MongoDB的基本操作 安装pymongo: pip install pymongo from pymongo import MongoClient import ...

  5. zabbix监控超详细搭建过程(转)

    监控及zabbix 目录: 1       监控分类... 1 1.1        硬件监控... 1 1.2        系统监控... 2 1.3        网络监控... 3 1.4   ...

  6. bzoj 1191: [HNOI2006]超级英雄Hero 网络流_残量网络

    题目描述: 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的 多少获得不同数目的奖品或奖金.主持人问题准备了若干道题目,只有当选手正确回答一道题后 ...

  7. 「Poetize4」创世纪

    在tyvj上怀疑爆栈了.....或许一定是我写挂了.以后调吧... UPD:bzoj上过了... 题解:https://blog.csdn.net/popoqqq/article/details/39 ...

  8. 编译htop

    git clone https://github.com/hishamhm/htop cd htop ./autogen.sh ./configure make make install

  9. 《黑白团团队》第八次团队作业:Alpha冲刺 第三天

    项目 内容 作业课程地址 任课教师首页链接 作业要求 团队项目 填写团队名称 黑白团团队 填写具体目标 认真负责,完成项目 团队项目Github仓库地址链接. 第三天 日期:2019/6/17 成员 ...

  10. Python中图像的缩放 resize()函数的应用

    cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst 参数说明: src - 原图 dst - 目标图像.当参数ds ...