浅谈Javascript中面向对象之对象
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了浅谈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
先就这么多后续更新
以上是关于浅谈Javascript中面向对象之对象的主要内容,如果未能解决你的问题,请参考以下文章