关于JavaScript面向对象的编程以下是我的理解,有不对的地方请指出;
JavaScript是一种基于对象的语言,遇到的东西几乎都是对象,但又不是完整的面向对象的语言,因为他的语法中没有类(class) ,使用中我们可以吧属性和方法封装成一个对象,有时候也会从原型对象中生成一个实例对象。我们可以通过下面代码实现:
我们先把猫看作一个对象,它有两个属性 : 颜色和名字 var cat ={ name :"", color: "" } 我们可以根据这个原型对象生成两个实例对象 var cat1 = {}; // 创建一个空对象 cat1.name = "大毛"; // 按照原型对象的属性赋值 cat1.color = "黄色"; var cat2 = {}; cat2.name = "二毛"; cat2.color = "黑色"; 这就是简单的封装了,把两个属性封装在一个对象里面。但是,这样的写法有两个缺点,一是如果多生成几个实例,写起来就非常麻烦;二是实例与原型之间,没有任何办法,可以看出有什么联系。
我们还可以用构造函数的模式,构造函数其实就是一个普通函数,但是在它内部使用了this变量,我们再用new对函数进行实例化,this变量也会绑定在实例对象上。
function Cat(name,color){ this.name=name; this.color=color; } 我们可以用new运算符生成实例对象 var cat1 = new Cat("大毛","黄色"); var cat2 = new Cat("二毛","黑色"); alert(cat1.name); // 大毛 alert(cat1.color); // 黄色
cat1和cat2 会自动含有constructor指向他们的构造函数
alert(cat1.constructor == Cat); //true alert(cat2.constructor == Cat); //true
我们还可以为cat添加不变的属性,比如type或者添加一个eat()方法,在这我们用一种节省内存的方法 来做,将不变的属性和方法直接定义到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(); // 吃老鼠
对于构造函数的继承我们说两种方法,一个是 prototype模式,一个是直接继承prototype对第一种的改进
有一个动物的构造函数 function Animal(){ this.species = "动物"; } 还有一个"猫"对象的构造函数。 function Cat(name,color){ this.name = name; this.color = color; }
现在用第一种方法继承
Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
Cat.prototype = new Animal();
代码的第一行,我们将Cat的prototype对象指向一个Animal的实例。
相当于完全删除了prototype 对象原先的值,然后赋予一个新值。
Cat.prototype.constructor = Cat;
第二行的意思是任何一个prototype对象都有一个constructor属性,指向它的构造函数。如果没有"Cat.prototype = new Animal();"这一行,Cat.prototype.constructor是指向Cat的;加了这一行以后,Cat.prototype.constructor指向Animal。
验证一下 alert(Cat.prototype.constructor == Animal); //true
每一个实例也有一个constructor属性,默认调用prototype对象的constructor属性
alert(cat1.constructor == Cat.prototype.constructor); // true
因此,在运行"Cat.prototype = new Animal();"这一行之后,cat1.constructor也指向Animal!所以我们要注意使用第二行,改constructor的值
还有一种就是 直接继承prototype,这是对上一种方法的改进,由于Animal对象中,不变的属性都可以直接写入Animal.prototype。所以,我们也可以让Cat()跳过 Animal(),直接继承Animal.prototype。
我们先将Animal对象改写
function Animal(){ } Animal.prototype.species = "动物";
将Cat的prototype对象,然后指向Animal的prototype对象,这样就完成了继承。
Cat.prototype = Animal.prototype; Cat.prototype.constructor = Cat; var cat1 = new Cat("大毛","黄色"); alert(cat1.species); // 动物
但是我们要注意的是第二行实际上把Animal.prototype对象的constructor属性也改掉了
alert(Animal.prototype.constructor); // Cat