阮一峰 JavaScript OOD 三部曲:

封装

JS 是一种基于对象(object-based)的语言. 但是JS不是一种真正的OOP语言, 因为语法中没有class.

以下就是简单的封装. 把两个属性封装在一个对象里面. 但是,这样的写法有缺陷.

1. 如果要多生成几个实例,写起来就非常麻烦.

2. 实例与原型之间,没有任何办法看出联系.

<script>
var Cat = {
name: '',
color: ''
}
var cat1 = {};
cat1.name = '黑猫';
cat1.color = '黑色'; var cat2 = {
name: '白猫',
color: '白色'
};
console.log(cat1);
console.log(cat2);
</script>

改进方法

我们可以写一个函数, 来解决代码重复的问题.

<script>
function dog(name, color) {
return {
name: name,
color: color
}
}
var dog1 = dog('二狗子','黑色');
var dog2 = dog('狗蛋儿','黄色'); console.log(dog1);
console.log(dog2);
</script>

构造函数

JS的构造函数和传统编程语言不同. 所谓"构造函数",其实就是一个普通函数, 但是内部可以使用this变量(JS this变量随笔), 并且this 变量会绑定在实例对象上. 只需要把function 名字首字母大写就来代表这个function是constructor

通过构造函数, 我们现在原型就可以这么写了:

    <script>
function Dog(name, color) {
this.name = name;
this.color = color;
}
var dog1 = new Dog('二狗子', '黑色');
var dog2 = new Dog('狗蛋儿', '黄色'); console.log(dog1);
console.log(dog2);
console.log(dog1.constructor === Dog); // true
          console.log(dog2.constructor === Dog); // true
      console.log(dog1 instanceof Dog); // true
      console.log(dog2 instanceof Dog); // true
</script>

构造函数的问题

构造函数方法很好用,但是存在一个浪费内存的问题. e.g.

这么做有一个弊端就是 property type 和 function eat()都是一模一样的内容, 每次生成一个实例, 都必须为重复的内容, 会多次占用内存. 这样缺乏效率和内存管理.

我们有办法像.NET 中引用类型的用法, 指向内存地址,从而节约内存使用.  这个方法就是prototype.

<script>
function Dog(name, color) {
this.name = name;
this.color = color;
this.type = '犬类';
this.eat = function() {console.log('啥都吃');};
}
var dog1 = new Dog('二狗子', '黑色');
var dog2 = new Dog('狗蛋儿', '黄色');
console.log(dog1.type) // 犬类
dog1.eat(); // 啥都吃 console.log(dog1.eat === dog2.eat); // false
</script>

http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html

prototype

JavaScript规定, 每个构造函数都有一个prototype属性, 指向另一个对象.  这个对象的所有属性和方法, 都会被构造函数实例继承.

prototype 用.NET 知识来解释, 可以认为是引用类型.  指向内存同一块

那什么时候使用prototype呢?  prototype应该储存那些在object中常被子类使用的公共类型而不经常改变的primitive和function.

使用prototype可以减少使用资源.

object里面其他的内容可以理解为值类型.

prototype chain

原型链是有OOD种继承的特性.

John 是从 Person 这个constructor中继承实例化得到的.  所以John的 __proto__ === Person.prototype // true

我们看到 __proto__ 底下还有 __proto__.  这是因为 我们Person 这个constructor的prototype 是从 object中继承实例化得到的. 所以Person的__proto__ 拥有所有object的__proto__的特性.

prototype 和 __proto__ 关系

在developer tool中, __proto__ 就是object 中的prototype property.

https://stackoverflow.com/questions/9959727/proto-vs-prototype-in-javascript

Object.Create 和 新实例化的function constructor的区别

Object.Create 只需要继承first argument(此例子中的calculateAge 这个function)

  Object.Create 的benefit 是可以让开发人员把一个非常复杂继承结构转换成一个简单的形式.

  因为开发人员可以直接的控制哪些prototype需要继承. 但是function constructor 需要继承所有的父中prototype.

新实例化的function constructor需要从继承的function constructor 里面继承所有的prototype property.

// Object.create
var personProto = {
calculateAge: function() {
console.log(2016 - this.yearOfBirth);
}
}; var john = Object.create(personProto);
john.name = "John";
john.yearOfBirth = 1990;
john.job = "teacher"; var jane = Object.create(personProto, {
name: {value: 'Jane'},
yearOfBirth: {value: 1969},
job: {value: 'dev'}
});

Prototype 的验证方法

JavaScript 定义了一些方法去验证, 帮助我们使用prototype.

    <script>
var Person = function (name, yearOfBirth, job) {
this.name = name;
this.yearOfBirth = yearOfBirth;
this.job = job;
} Person.prototype.calculateAge = function () {
console.log(2016 - this.yearOfBirth);
}
Person.prototype.type = '哺乳动物'; var john = new Person('John', 1990, 'teacher');
var jane = new Person('Jane', 1969, 'designer');
var mark = new Person('Mark', 1948, 'retried');
</script>

isPrototypeOf()

这个method用来潘丹prototype对象和实例之间的关系.

console.log(Person.prototype.isPrototypeOf(john)); //true

console.log(Person.prototype.isPrototypeOf(jane)); //true

hasOwnProperty()

这个method是用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性.

console.log(john.hasOwnProperty("name")); // true

console.log(john.hasOwnProperty("type")); // false

in 运算符

in 运算符可以用来判断某个实例是否含有某个属性. 不管是不是本地属性

console.log("name" in john); // true
console.log("type" in jane); // true

JavaScript Constructor & prototype的更多相关文章

  1. 彻底搞清javascript中this, constructor, prototype

    说起这三个属性,肯定有一些同学和我一样,初学js时非常困惑,头大,一脸的迷茫.今天就来给大家彻底解决这些担心受怕的问题. 先看this this定义: this就是函数赖以执行的对象. 分析这句话: ...

  2. javascript 之 prototype 浅析

    prototype 原型 javascript 是一种 prototype based programming 的语言, 而与我们通常的 class based programming 有很大 的区别 ...

  3. Javascript: 从prototype漫谈到继承(2)

    本文同时也发表在我另一篇独立博客 <Javascript: 从prototype漫谈到继承(2)>(管理员请注意!这两个都是我自己的原创博客!不要踢出首页!不是转载!已经误会三次了!) 上 ...

  4. 在 JavaScript 中 prototype 和 __proto__ 有什么区别

    本文主要讲三个 问题 prototype 和 proto function 和 object new 到底发生了什么 prototype 和 proto 首先我们说下在 JS 中,常常让我们感到困惑的 ...

  5. Javascript中prototype属性

    prototype作为JS相对比较难理解的一个知识点,在这里发表下自己的理解. 本文将包含以下几部分内容: 1.js prototype的简单介绍, 2.js构造函数的介绍, 3.prototype的 ...

  6. js老生常谈之this,constructor ,prototype

    前言 javascript中的this,constructor ,prototype,都是老生常谈的问题,深入理解他们的含义至关重要.在这里,我们再来复习一下吧,温故而知新! this this表示当 ...

  7. Javascript中prototype属性详解 (存)

    Javascript中prototype属性详解   在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...

  8. JavaScript constructor 属性详解

    对象的constructor属性用于返回创建该对象的函数,也就是我们常说的构造函数. 在JavaScript中,每个具有原型的对象都会自动获得constructor属性.除了arguments.Enu ...

  9. javascript继承—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承-prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

随机推荐

  1. 文件上传FormData

    <div class="modal-dialog"> <div class="modal-content"> <div class ...

  2. 第三节 java 数组(循环遍历、获取数组的最值(最大值和最小值)、选择排序、冒泡排序、练习控制台输出大写的A)

    获取数组的最值(最大值和最小值) 思路: 1.获取最值需要进行比较,每一次比较都会有一个较大的值,因为该 值不确定,需要一个变量进行临储. 2.让数组中的每一个元素都和这个变量中的值进行比较,如果大于 ...

  3. Android开发 ---xml布局元素

    1.android:orientation="vertical/horizontal" vertical为垂直布局, horizontal为水平布局 2.android:layou ...

  4. mybatis 异常 There is no getter for property named 'bizId' in 'class java.lang.Long'

    mybatis 异常 There is no getter for property named 'bizId' in 'class java.lang.Long' 当使用mybatis进行传参的时候 ...

  5. Oracle 定时器

    我的代码 declare job number; begin dbms_job.submit( JOB=>job, what=>'addBytime;',// 这里要写分号,不然容易出错. ...

  6. day 26面向对象 的封装 接口 抽象

    大纲分析 # 面向对象# 类 :一类具有相同属性和方法的事物 #类的定义:class #类中可以定义的方法种类: #普通方法 self 对象 #类方法 cls @classmethod 类/对象 #静 ...

  7. ubantu查看进程操作

    可以使用ps命令.它能显示当前运行中进程的相关信息,包括进程的PID.Linux和UNIX都支持ps命令,显示所有运行中进程的相关信息. ps命令能提供一份当前进程的快照.如果想状态可以自动刷新,可以 ...

  8. 将numpy array由浮点型转换为整型

    使用numpy中的astype()方法可以实现,示例如下: x Out[20]: array([[ 5. , 4. ], [ 4. , 4.33333333], [ 3.66666667, 4.5 ] ...

  9. python day05字典

    一.字典 1.字典的结构: a={key:value,key2:value},key是不可变的,value是可变的. 例子:dic = {123: 456, True: 999, "id&q ...

  10. JAVA_全局配置文件(配置网址,url等等)_第一种方式

    一.概述 当使用httpClient调其他系统接口时,需要通过地址来发送post请求. 这时我们有不同的环境,那么就有两个问题. 1是地址不能写在代码中,而是要写在配置文件. 2是不同环境配置文件应该 ...