浅谈Javascript中面向对象之对象

一、对象

1.1创建对象

Javascript是一种基于对象(object-based)的语言,你遇到的所有东西几乎都是对象。
一个简单的对象创建:

var People = {
    name : "eavan",
    age : 24,
    getName : function(){
        alert(this.name);        //eavan
    }
}

使用的时候就可以用People.name,获取People这个对象的name属性,或者是People.getName()来得到People的name值。
另一种对象创建方式:

var People = new Object();
People.name = "eavan";
People.age = 24;
People.getName = function(){
    alert(this.name);
}
    

这里用到了new,就顺便提一下在使用new的时候发生了什么,其实在使用new的时候,大致可以认为做了这三件事,看下面的代码:

var People  = {};                      //我们创建了一个空对象People
People.__proto__ = Object.prototype;   //我们将这个空对象的__proto__成员指向了Object函数对象prototype成员对象
Object.call(People);         //我们将Object函数对象的this指针替换成People,然后再调用Object函数
1.2封装

简单来说就是对一些属性的隐藏域暴露,比如私有属性、私有方法、共有属性、共有方法、保护方法等等。而js也能实现私有属性、私有方法、共有属性、共有方法等等这些特性。

像java这样的面向对象的编程语言一般会有一个类的概念,从而实现封装。而javascript中没有类的概念,JS中实现封装主要还是靠函数。

首先声明一个函数保存在一个变量里面。然后在这个函数(类)的内部通过对this变量添加属性或者方法来实现对类添加属相或者方法。

var Person = function(){
    var name = "eavan";             //私有属性
    function checkName(){};         //私有方法

    this.myName = "gaof";            //对象共有属性
    this.myFriends = ["aa","bb","cc"];
    this.copy = function(){}         //对象共有方法

    this.getName = function(){       //构造器方法
        return name;
    };
}

纯构造函数封装数据的问题是:对像this.copy = function(){}这种方法的创建,其实在执行的时候大可不必绑定到特定的对象上去,将其定义到全局变量上也是一样的,而且其过程相当于实例化了一个Function,也大可不必实例化这么多其实干同一件事的方法。而这个小问题的解决可以用原型模式来解决。

1.3理解原型

在每创建一个函数的时候,都会生成一个prototype属性,这个属性指向函数的原型对象。而其是用来包含特定类型的所有实例共享的属性和方法。所以,直接添加在原型中的实例和方法,就会被所有实例所共享。

同样还是上面的Person的例子,我们可以为其原型添加新的属性和方法。

Person.isChinese = true;                          //类的静态共有属性(对象不能访问)
Person.prototype.sex = "man" ;            //类的共有属性
Person.prototype.frends = ["gao","li","du"];
Person.prototype.isBoy = function(){};    //类的共有方法

原型封装数据的问题:对绑定在prototype上的引用类型的变量,由于被所有对象所共有,其中某一个对象对该数据进行修改,当别的对象访问该数据的时候,所访问到的值就是被修改后的。
比如如下代码:

var person1 = new Person();
person1.frends.push("dd");
console.log(person1.frends);    //["gao", "li", "du", "dd"]
var person2 = new Person();
person2.frends.push("ee");
console.log(person2.frends);     //["gao", "li", "du", "dd", "ee"]

原本希望对person1和person2的friends属性分别添加新的内容,结果二者的friends属性居然是“公用”的!

综上,最常见的方式应该是组合使用构造函数和原型模式,构造函数用于定义实例属性,原型模式用于定义方法和共享的属性。

每个类有三部分构成:第一部分是构造函数内,供实例对象化复制用。第二部分是构造函数外,直接通过点语法添加,供类使用,实例化对象访问不到。第三部分是类的原型中,实例化对象可以通过其原型链间接访问到,也是为所有实例化对象所共用。

在说到对象实例的属性的时候,我们有一个问题,就是在访问一个属性的时候,这个属性是属于实例,还是属于这个实例的原型的呢?

比如还是上面的例子,我们为person2实例增加一个sex属性,这时候访问person2的sex属性时,得到的是我们增加的值。说明为对象实例添加一个属性的时候,这个属性就会屏蔽原型对象中保存的同名属性。

   person2.sex = "woman";
    console.log(person1.sex);                //man
    console.log(person2.sex);                //woman

这个时候我们可以使用hasOwnProperty()方法来检测一个属性是存在于实例中,还是存在于原型中。如果实例中有这个属性,hasOwnProperty()会返回true,而hasOwnProperty()并不会感知到原型中的属性。所以可以用这个方法检测属性到底是存在于实例中还是原型中。

console.log(person1.hasOwnProperty("sex"));        //原型中的属性,返回false
console.log(person2.hasOwnProperty("sex"));        //实例中的属性,返回true

先就这么多后续更新

时间: 2024-12-26 23:26:33

浅谈Javascript中面向对象之对象的相关文章

浅谈javascript中的包装对象

javascript中的对象类型分为内置类型和对象类型,其中内置类型包括sting number boolean null undefined五种:对象类型包括Array Function regExp Date 等等,统称为Object类型.我们知道在一个对象中包含一系列属性名/属性值的集合,可以通过"."来访问对象的属性或方法,如: 1 window.onload=function(){//可执行代码} 但我们常常可以看到这样的代码: 1 var str="hello w

通过一道笔试题浅谈javascript中的promise对象

因为前几天做了一个promise对象捕获错误的面试题目,所以这几天又重温了一下promise对象.现在借这道题来分享下一些很基础的知识点. 下面是一个面试题目,三个promise对象捕获错误的例子,返回结果有什么不同. //使用throw添加错误事件 var p = new Promise(function(resolve, reject) { resolve("ok"); throw new Error('error0'); //setTimeout(function() { thr

浅谈JavaScript中的原型模式

在JavaScript中创建对象由很多种方式,如工厂模式.构造函数模式.原型模式等: <pre name="code" class="html">//工厂模式 function createPerson(name,age,job) { var o = new Object; o.name = name; o.age = age; o.job = job; o.sayName = function() { alert(this.name); } retur

浅谈javascript中的call、apply、bind

apply.call 在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念. 先来一个栗子: function fruits() {} fruits.prototype = { color: "red", say: function() { console

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

写在前面 既然是浅谈,就不会从原理上深度分析,只是帮助我们更好地理解... 面向对象与面向过程 面向对象和面向过程是两种不同的编程思想,刚开始接触编程的时候,我们大都是从面向过程起步的,毕竟像我一样,大家接触的第一门计算机语言大概率都是C语言,C语言就是一门典型的面向过程的计算机语言.面向过程主要是以动词为主,解决问题的方式是按照顺序一步一步调用不同的函数.面向对象是以名词为主,将问题抽象出具体的对象,而这个对象有自己的属性和方法,在解决问题的时候,是将不同的对象组合在一起使用. //面向过程装

浅谈JavaScript中继承的实现

  谈到js中的面向对象编程,都有一个共同点,选择原型属性还是构造函数,两者各有利弊,而就片面的从js的对象创建以及继承的实现两个方面来说,官方所推荐的是两个相结合,各尽其责,各取其长,在前面的例子中,我已就在JavaScript中对象创建的方法做了一些总结,下面就其继承来道说一二:   1:原型链继承: 每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象内部的指针(默认的原型,所有默认类型都继承了Object,而这个继承也是用过原型链实现) fu

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

本文继续讲解JavaScript的面向对象程序设计.继承是面向对象语言中的一个基本概念,面向对象语言支持两种继承实现方式:接口继承和实现继承.接口继承只继承方法签名,而实现继承则继承实际的方法.但是在JavaScript中函数时没有签名的,所以无法实现接口继承.JavaScript支持实现继承,而且其实现继承主要是通过原型链继承的. 原型链 JavaScript中有原型链的概念,并将原型链作为实现继承的主要方法.基本实现思想是让一个函数的原型继承另外一个函数的原型的属性和方法.每一个函数都有一个

浅谈javascript中的闭包

引入定义:闭包只有权访问另一个函数中的作用域中的函数. 简单点说,就是当某函数a执行完毕后,闭包不会使得GC(JavaScript的回收机制)去回收a所占用的资源,因为a的内部函数b的执行需要依赖a中的变量. 代码示例: window.onload = function(){ function createComparisonFunction(propertyName){ return function(object1, object2){ var value1 = object1[proper

浅谈javascript中的For in语法

相信大家都使用过javascript中的for循环,主要用来遍历数组对象,方便执行重复操作,体现代码的重用性.但是,应为数组的索引一般是整 型的数字,当遇到JSON对象或者object对象时,就不能使用for循环遍历了,应当使用for in函数遍历对象,这里就谈谈个人对for in的理解. 首先,虽然叫For in语法但关键字还是用for,这个语法还可以用来遍历对象,拿到的是对象的属性名称,然后通过对象名[属性名称]就可以拿到对象.个人觉得,理解这个语法的本质,关键在于理解每次循环得到的到底是什