js是一门基于面向对象编程的语言.
      如果我们要把(属性)和(方法)封装成一个对象,甚至要从原型对象生成一个实例,我们应该怎么做呢?

 一.生成对象的原始模式
            假定把猫看成一个对象,它有name和color两个属性.
            var cat = {
                name:'',
                color:''
            }
            
            现在,我们需要根据这个原型对象的规格,生成两个实例对象.
            var cat1 = {};//创建一个空对象
            cat1.name = "大毛";//按照原型对象的属性赋值
            cat1.color = "黄色"
            
            var cat2 = {};
            cat2.name = "二毛";
            cat2.color = "黑色"
            
            这是最简单的封装了,把两个属性封装在一个对象里面.但是,这样的写法有两个缺点:1.如果多生成几个实例,写起来就非常麻烦;2.实例和原型之间,没有任何办法,可以看出有什么联系.
        
        二.原始模式的改进
            写一个函数,解决代码的重复问题
            function Cat(name,color){
                return {
                    name:name,
                    color:color
                }
            }
            然后生成实例对象,就等于在调用函数:
            var cat1 = Cat("大毛","黄色");
            var cat2 = Cat("二毛","黑色");
        
            这个方法的问题依然是,cat1 和 cat2 之间没有内在联系,不能反映出他们是同一个原型对象的实例.
            
        三.构造函数模式
            为了解决从原型对象生成实例的问题,js 提供了一种构造函数( constructor )模式.
            所谓"构造函数",其实就是一个普通函数,内部使用了this变量. 对构造函数使用 new 运算符,就能生成实例, 并且 this 对象会绑定在实例对象上.
            
            比如,猫的原型对象可以这样写,
            function Cat(name,color){
                this.name = name;
                this.color = color;
            }
            现在,我们就可以生成实例对象了:
            var cat1 = new Cat("大毛","黄色");
            var cat2 = new Cat("二毛","黑色");
            alert(cat1.name);//大毛
            alert(cat2.name);//二毛
            console.log(cat1);//Cat{name: "大毛", color: "黄色"}(constructor)
            
            这时,cat1 和 cat2 会自动含有一个 constructor 属性, 指向他们的构造函数.
            console.log(cat1.constructor === Cat);//true
            console.log(cat2.constructor === Cat);//true
            js还提供了一个 instanceof 运算符, 验证原型对象与实例对象之间的关系.
            alert(cat1 instanceof Cat);//true
            alert(cat2 instanceof Cat);//true    

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0.1-1 面向对象</title>
</head>
<body>
<script>
//构造函数
function Cat(name,color){
this.name = name;
this.color = color;
} //生成实例(实例化)
var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色"); //验证
alert(cat1.name);
alert(cat2.name); console.log(cat1.constructor === Cat);
console.log(cat2.constructor === Cat); alert(cat1 instanceof Cat);
alert(cat2 instanceof Cat);
</script>
</body>
</html>

四.构造函数模式的问题
            构造函数方法很好用,但是存在一个浪费内存的问题.
            请看,我们现在为Cat对象添加一个不变属性type(种类),和一个方法eat(吃).那么,原型对象 Cat 就变成了下面这样:
            function Cat(name,color){
                this.name = name;
                this.color = color;
                this.type = "猫科动物";
                this.eat = function(){
                    alert("吃老鼠");
                }
            }
            采用同样的方法,生成实例:
            var cat1 = new Cat("大毛","黄色");
            var cat2 = new Cat("二毛","黑色");
            alert(cat1.type);//猫科动物
            cat2.eat();//吃老鼠

 <!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>0.1-2 面向对象(一)</title>
</head>
<body>
<script>
//构造函数
function Cat(name,color){
this.name = name;
this.color = color;
this.type = "猫科动物";
this.eat = function(){
alert("吃老鼠");
}
} //生成实例
var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.type);//猫科动物
cat2.eat();//吃老鼠
alert(cat1.eat == cat2.eat);//false
alert(cat1.eat);
</script>
</body>
</html>

表面上,好像没有什么问题,但是实际上这样做,有一个很大的弊端.那就是,对于每一个实例对象,type属性和eat方法都是一某一样得内容,每一次生成一个实例,都必须为重复的内容,多占一些内存.这样既不环保,也缺乏效率.
            alert(cat1.eat == cat2.eat);//false
            
            能不能让type属性和eat()方法在内存中只生成一次,然后所有实例都指向那个内存地址呢?回答是可以的.
            
        五.Prototype模式
            js规定, 每一个构造函数都有一个 prototype 属性, 指向另一个对象. 这个对象上所有属性和方法, 都会被构造函数的实例继承.
            这就意味着,我们可以把那些不变的属性和方法, 直接定义在prototype对象上.
            function Cat(name,color){
                this.name = name;
                this.color = color;
            }
            Cat.prototype.type = "猫科动物";
            Cat.prototype.eat = function(){
                alert("吃老鼠");
            }
            //生成实例
            var cat1 = new Cat("大毛","黄色");
            var cat2 = new Cat("二毛","黑色");
            alert(cat1.type);//猫科动物
            cat1.eat();//吃老鼠
            
            这时所有实例的type属性和eat()方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运算效率.
            alert(cat1.eat == cat2.eat);//true
            
        六.Prototype模式的验证方法
            为了配合 prototype 属性, js定义了一些辅助方法, 帮助我们使用它.
            6.1 isPrototypeOf()
                这个方法用来判断, 某个prototype对象和某个实例之间的关系.
                alert(Cat.prototype.isPrototypeOf(cat1));//true
                alert(Cat.prototype.isPrototypeOf(cat2));//true
            6.2 hasOwnProperty()
                每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性, 还是继承自 prototype 的属性。
                alert(cat1.hasOwnProperty("name"));//true
                alert(cat1.hasOwnProperty("type"));//false
            6.3 in 运算符
                1. in 运算符可以用来判断,某个实例是否具有某个属性,不管是不是本地属性.
                    alert("name" in cat1);//true
                    alert("type" in cat2);//true
                
                2. in运算符还可以用来遍历某个对象的所有属性
                    for(var prop in cat1){alert("cat1["+prop+"]="+cat1[prop])}

    

 <!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>0.1-3 面向对象(一)</title>
</head>
<body>
<script>
//构造函数
function Cat(name,color){
this.name = name;
this.color = color;
}
Cat.prototype.type = "猫科动物";
Cat.prototype.eat = function(){
alert("吃老鼠");
}
//生成实例
var cat1 = new Cat("大毛","黄色");
var cat2 = new Cat("二毛","黑色");
alert(cat1.type);
cat1.eat();
alert(cat1.eat == cat2.eat); alert(Cat.prototype.isPrototypeOf(cat1));
alert(Cat.prototype.isPrototypeOf(cat2)); alert(cat1.hasOwnProperty("name"));
alert(cat1.hasOwnProperty("type")); alert("name" in cat1);
alert("type" in cat2); for(var prop in cat1){alert("cat1["+prop+"]="+cat1[prop])}
</script>
</body>
</html>

总结:这一部分主要介绍了如何"封装"数据和方法, 以及如何从原型对象中生成实例.

原文链接:http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html

JS面向对象编程(一):封装的更多相关文章

  1. 前端js面向对象编程以及封装组件的思想

    demo-richbase 用来演示怎么使用richbase来制作组件的例子 作为一名前端工程师,写组件的能力至关重要.虽然javascript经常被人嘲笑是个小玩具,但是在一代代大牛的前仆后继的努力 ...

  2. 关于前端js面向对象编程以及封装组件的思想

    demo-richbase 用来演示怎么使用richbase来制作组件的例子 作为一名前端工程师,写组件的能力至关重要.虽然javascript经常被人嘲笑是个小玩具,但是在一代代大牛的前仆后继的努力 ...

  3. 带你一分钟理解闭包--js面向对象编程

    上一篇<简单粗暴地理解js原型链--js面向对象编程>没想到能攒到这么多赞,实属意外.分享是个好事情,尤其是分享自己的学习感悟.所以网上关于原型链.闭包.作用域等文章多如牛毛,很多文章写得 ...

  4. JS面向对象编程(进阶理解)

    JS 面向对象编程 如何创建JS对象 JSON语法声明对象(直接量声明对象) var obj = {}; 使用 Object 创建对象 var obj = new Object(); JS对象可以后期 ...

  5. 页面循环绑定(变量污染问题),js面向对象编程(对象属性增删改查),js字符串操作,js数组操作

    页面循环绑定(变量污染问题) var lis = document.querySelectorAll(".ul li") for ( var i = 0 ; i < lis. ...

  6. Js面向对象编程

    Js面向对象编程 1.     什么是面向对象编程? 我也不说不清楚什么是面向对象,反正就那么回事吧. 编程有时候是一件很快乐的事,写一些小游戏,用编程的方式玩游戏等等 2.     Js如何定义一个 ...

  7. js原生设计模式——3简单工厂模式\js面向对象编程实例

    <!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8&qu ...

  8. (一)Javascript 面向对象编程:封装

    Javascript 面向对象编程:封装 作者:阮一峰 Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象.但是,它又不是一种真正的面向对象编程(OOP ...

  9. js面向对象编程 ---- 系列教程

    原 js面向对象编程:数据的缓存 原 js面向对象编程:如何检测对象类型 原 js面向对象编程:if中可以使用那些作为判断条件呢? 原 js面向对象编程:this到底代表什么?第二篇 原 js面向对象 ...

  10. 简单粗暴地理解js原型链–js面向对象编程

    简单粗暴地理解js原型链–js面向对象编程 作者:茄果 链接:http://www.cnblogs.com/qieguo/archive/2016/05/03/5451626.html 原型链理解起来 ...

随机推荐

  1. HBase 学习之路(一)—— HBase简介

    一.Hadoop的局限 HBase是一个构建在Hadoop文件系统之上的面向列的数据库管理系统. 要想明白为什么产生HBase,就需要先了解一下Hadoop存在的限制?Hadoop可以通过HDFS来存 ...

  2. Python初探-基础篇

    python和其他语言其实是相似的,如果你会了另一门语言,那学习这个语言,会很快上手 1.mac下自带的有python,版本为2.7.0(可以用home brew python3 安装最新版本的pyt ...

  3. Windows上安装PyV8

    Windows上安装PyV8 在PyPi网站上有Windows的exe格式的包连接, PyPi, Google注意网络是否通畅! 官网地址 Google PyV8 双击安装, 注意, 一般会自动检测P ...

  4. 快速接入业务监控体系,grafana监控的艺术

    做一个系统,如果不做监控,是不完善的. 如果为做一个快速系统,花力气去做监控,是不值得的. 因为,我们有必要具备一个能够快速建立监控体系的能力.即使你只是一个普通开发人员! 个人觉得,做监控有三个核心 ...

  5. sql语句一些简单的用法

  6. 高并发架构系列:Redis缓存和MySQL数据一致性方案详解

    一.需求起因 在高并发的业务场景下,数据库大多数情况都是用户并发访问最薄弱的环节.所以,就需要使用redis做一个缓冲操作,让请求先访问到redis,而不是直接访问MySQL等数据库. 这个业务场景, ...

  7. Java web导出word,文件名为中文,%E6%9D%90%E8%B4%A8%E5%8D%95乱码

    因为文件名为中文,导出时会有乱码问题 原代码: String fileName = "文件名.doc"; response.setHeader("Content-Disp ...

  8. cogs.12运输问题2题解

    乍一看貌似和运输问题1没有任何区别,但本题有一个有意思的东西叫做下限,我个人称之为非强制下限,因为本题中要求的实际是我走这条边这条边才至少走下限的流,虽然出题人没说,但从样例来看确实是这样的,而强制下 ...

  9. [NOIP2003] 传染病控制题解

    问题 F: [NOIP2003] 传染病控制 时间限制: 1 Sec  内存限制: 128 MB 题目描述 [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范 ...

  10. Python-入门学习

    开始学习Python(围绕windows 平台上),记录一些点滴的知识点,也希望可以和大家交流分享. ================================================= ...