老生常谈javascript的面向对象思想
面向对象的三大基本特性
封装(把相关的信息(无论数据或方法)存储在对象中的能力)
继承(由另一个类(或多个类)得来类的属性和方法的能力)
多态(一个对象在不同情况下的多种形态)
定义类或对象
第一种:基于object对象
var person = new object(); person.name = "rose"; person.age = 18; person.getname = function () { return this.name; }; console.log(person.name);//rose console.log(person.getname);//function () {return this.name;} console.log(person.getname());//rose
缺点:不能创建多个对象。
第二种:基于字面量方式
var person = { name : "rose", age : 18 , getname : function () { return this.name; } }; console.log(person.name);//rose console.log(person.getname);//function () {return this.name;} console.log(person.getname());//rose
优点:比较清楚的查找对象包含的属性和方法;
缺点:不能创建多个对象。
第三种:工厂模式
方式一:
function createperson(name,age) { var object = new object(); object.name = name; object.age = age; object.getname = function () { return this.name; }; return object; } var person1 = createperson("rose",18); var person2 = createperson("jack",20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname);//false//重复生成函数,为每个对象都创建独立的函数版本
优点:可以创建多个对象;
缺点:重复生成函数getname(),为每个对象都创建独立的函数版本。
方式二:
function createperson(name,age) { var object = new object(); object.name = name; object.age = age; object.getname = getname; return object; } function getname() { return this.name; } var person1 = createperson("rose",18); var person2 = createperson("jack",20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname);//true//共享同一个函数
优点:可以创建多个对象;
缺点:从语义上讲,函数getname()不太像是person对象的方法,辨识度不高。
第四种:构造函数方式
方式一:
function person(name,age) { this.name = name; this.age = age; this.getname = function () { return this.name; } } var person1 = new person("rose",18); var person2 = new person("jack",20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname); //false//重复生成函数,为每个对象都创建独立的函数版本
优点:可以创建多个对象;
缺点:重复生成函数getname(),为每个对象都创建独立的函数版本。
方式二:
function person(name,age) { this.name = name; this.age = age; this.getname = getname ; } function getname() { return this.name; } var person1 = new person("rose",18); var person2 = new person("jack",20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname); //true//共享同一个函数
优点:可以创建多个对象;
缺点:从语义上讲,函数getname()不太像是person对象的方法,辨识度不高。
第五种:原型方式
function person() { } person.prototype.name = 'rose'; person.prototype.age = 18; person.prototype.getname = function () { return this.name; }; var person1 = new person(); var person2 = new person(); console.log(person1.name);//rose console.log(person2.name);//rose//共享同一个属性 console.log(person1.getname === person2.getname);//true//共享同一个函数
缺点:它省略了为构造函数传递初始化参数,这在一定程序带来不便;另外,最主要是当对象的属性是引用类型时,它的值是不变的,总是引用同一个外部对象,所有实例对该对象的操作都会影响其它实例:
function person() { } person.prototype.name = 'rose'; person.prototype.age = 18; person.prototype.lessons = ["语文","数学"]; person.prototype.getname = function () { return this.name; }; var person1 = new person(); person1.lessons.push("英语"); var person2 = new person(); console.log(person1.lessons);//["语文", "数学", "英语"] console.log(person2.lessons);//["语文", "数学", "英语"]//person1修改影响了person2
第六种:构造函数+原型方式(推荐)
function person(name,age) { this.name = name; this.age = age; } person.prototype.getname = function () { return this.name; }; var person1 = new person('rose', 18); var person2 = new person('jack', 20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname);//true//共享原型中定义的方法
缺点:属性定义在构造函数内,方法定义在构造函数外,与面向对象的封装思想不符。
第七种:构造函数+动态原型方式(推荐)
方式一:
function person(name,age) { this.name = name; this.age = age; if (typeof person._getname === "undefined"){ person.prototype.getname = function () { return this.name; }; person._getname = true; } } var person1 = new person('rose', 18); var person2 = new person('jack', 20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname);//true//共享原型中定义的方法
方式二:
function person(name,age) { this.name = name; this.age = age; if (typeof this.getname !== "function"){ person.prototype.getname = function () { return this.name; }; } } var person1 = new person('rose', 18); var person2 = new person('jack', 20); console.log(person1.name);//rose console.log(person2.name);//jack console.log(person1.getname === person2.getname);//true//共享原型中定义的方法
对象属性的扩展及删除
javascript的对象可以使用 '.' 操作符动态的扩展其属性,可以使用 'delete' 关键字或将属性的值设置为 'undefined' 来删除属性。
function person(name,age) { this.name = name; this.age = age; if (typeof person._getname === "undefined"){ person.prototype.getname = function () { return this.name; }; person._getname = true; } } var person = new person("rose",18); person.job = 'engineer';//添加属性 console.log(person.job);//engineer delete person.job;//删除属性 console.log(person.job);//undefined//删除属性后值为undefined person.age = undefined;//删除属性 console.log(person.age);//undefined//删除属性后值为undefined
对象属性类型
数据属性
特性:
[configurable]:表示能否使用delete操作符删除从而重新定义,或能否修改为访问器属性。默认为true;
[enumberable]:表示是否可通过for-in循环返回属性。默认true;
[writable]:表示是否可修改属性的值。默认true;
[value]:包含该属性的数据值。读取/写入都是该值。默认为undefined;如上面实例对象person中定义了name属性,其值为'my name',对该值的修改都反正在这个位置
function person(name,age) { this.name = name; this.age = age; if (typeof person._getname === "undefined"){ person.prototype.getname = function () { return this.name; }; person._getname = true; } } var person = new person("rose",18); object.defineproperty(person,"name",{configurable:false,writable:false}); person.name = "jack"; console.log(person.name);//rose//重新赋值无效 delete person.name; console.log(person.name);//rose//删除无效
注意:
一旦将configurable设置为false,则无法再使用defineproperty将其修改为true(执行会报错:cannot redefine property : propertyname)
function person(name,age) { this.name = name; this.age = age; if (typeof person._getname === "undefined"){ person.prototype.getname = function () { return this.name; }; person._getname = true; } } var person = new person("rose",18); object.defineproperty(person,"name",{configurable:false,writable:false}); person.name = "jack"; console.log(person.name);//rose//重新赋值无效 delete person.name; console.log(person.name);//rose//删除无效 object.defineproperty(person,"name",{configurable:true,writable:true});//cannot redefine property: name
访问器属性
特性:
[configurable]:是否可通过delete操作符删除重新定义属性;
[numberable]:是否可通过for-in循环查找该属性;
[get]:读取属性时调用,默认:undefined;
[set]:写入属性时调用,默认:undefined;
访问器属性不能直接定义,必须使用defineproperty()或defineproperties来定义:如下
function person(name,age) { this.name = name; this._age = age; if (typeof person._getname === "undefined"){ person.prototype.getname = function () { return this.name; }; person._getname = true; } } var person = new person("rose",18); object.defineproperty(person,"age",{ get:function () { return this._age; }, set:function (age) { this._age = age; }}); person.age = 20; console.log(person.age);//20//person.age=20是使用set方法将20赋值给_age,person.age是使用get方法将_age的读取出来 console.log(person._age);//20
获取所有的属性和属性的特性
使用object.getownpropertynames(object)方法可以获取所有的属性;
使用object.getownpropertydescriptor(object,property)方法可以取得给定属性的特性;
function person(name,age) { this.name = name; this._age = age; if (typeof person._getname === "undefined"){ person.prototype.getname = function () { return this.name; }; person._getname = true; } } var person = new person("rose",18); object.defineproperty(person,"age",{ get:function () { return this._age; }, set:function (age) { this._age = age; }}); console.log(object.getownpropertynames(person));//["name", "_age", "age"] console.log(object.getownpropertydescriptor(person,"age"));//{enumerable: false, configurable: false, get: function, set: function}
对于数据属性,可以取得:configurable,enumberable,writable和value;
对于访问器属性,可以取得:configurable,enumberable,get和set;
继承机制实现
对象冒充
function father(name) { this.name = name ; this.getname = function () { return this.name; } } function son(name,age) { this._newmethod = father; this._newmethod(name); delete this._newmethod; this.age = age; this.getage = function () { return this.age; } } var father = new father("tom"); var son = new son("jack",18); console.log(father.getname());//tom console.log(son.getname());//jack//继承父类getname()方法 console.log(son.getage());//18
多继承(利用对象冒充可以实现多继承)
function fathera(name) { this.name = name ; this.getname = function () { return this.name; } } function fatherb(job) { this.job = job; this.getjob = function () { return this.job; } } function son(name,job,age) { this._newmethod = fathera; this._newmethod(name); delete this._newmethod; this._newmethod = fatherb; this._newmethod(job); delete this._newmethod; this.age = age; this.getage = function () { return this.age; } } var fathera = new fathera("tom"); var fatherb = new fatherb("engineer"); var son = new son("jack","programmer",18); console.log(fathera.getname());//tom console.log(fatherb.getjob());//engineer console.log(son.getname());//jack//继承父类fathera的getname()方法 console.log(son.getjob());//programmer//继承父类fatherb的getjob()方法 console.log(son.getage());//18
call()方法
function father(name) { this.name = name ; this.getname = function () { return this.name; } } function son(name,job,age) { father.call(this,name); this.age = age; this.getage = function () { return this.age; } } var father = new father("tom"); var son = new son("jack","programmer",18); console.log(father.getname());//tom console.log(son.getname());//jack//继承父类getname()方法 console.log(son.getage());//18
多继承(利用call()方法实现多继承)
function fathera(name) { this.name = name ; this.getname = function () { return this.name; } } function fatherb(job) { this.job = job; this.getjob = function () { return this.job; } } function son(name,job,age) { fathera.call(this,name); fatherb.call(this,job); this.age = age; this.getage = function () { return this.age; } } var fathera = new fathera("tom"); var fatherb = new fatherb("engineer"); var son = new son("jack","programmer",18); console.log(fathera.getname());//tom console.log(fatherb.getjob());//engineer console.log(son.getname());//jack//继承父类fathera的getname()方法 console.log(son.getjob());//programmer//继承父类fatherb的getjob()方法 console.log(son.getage());//18
apply()方法
function father(name) { this.name = name ; this.getname = function () { return this.name; } } function son(name,job,age) { father.apply(this,new array(name)); this.age = age; this.getage = function () { return this.age; } } var father = new father("tom"); var son = new son("jack","programmer",18); console.log(father.getname());//tom console.log(son.getname());//jack//继承父类getname()方法 console.log(son.getage());//18
多继承(利用apply()方法实现多继承)
function fathera(name) { this.name = name ; this.getname = function () { return this.name; } } function fatherb(job) { this.job = job; this.getjob = function () { return this.job; } } function son(name,job,age) { fathera.apply(this,new array(name)); fatherb.apply(this,new array(job)); this.age = age; this.getage = function () { return this.age; } } var fathera = new fathera("tom"); var fatherb = new fatherb("engineer"); var son = new son("jack","programmer",18); console.log(fathera.getname());//tom console.log(fatherb.getjob());//engineer console.log(son.getname());//jack//继承父类fathera的getname()方法 console.log(son.getjob());//programmer//继承父类fatherb的getjob()方法 console.log(son.getage());//18
原型链方法
function father() { } father.prototype.name = "tom"; father.prototype.getname = function () { return this.name; }; function son() { } son.prototype = new father(); son.prototype.age = 18; son.prototype.getage = function () { return this.age; }; var father = new father(); var son = new son(); console.log(father.getname());//tom console.log(son.getname());//tom//继承父类fathera的getname()方法 console.log(son.getage());//18
混合方式(call()+原型链)
function father(name) { this.name = name; } father.prototype.getname = function () { return this.name; }; function son(name,age) { father.call(this,name); this.age = age; } son.prototype = new father(); son.prototype.getage = function () { return this.age; }; var father = new father("tom"); var son = new son("jack",18); console.log(father.getname());//tom console.log(son.getname());//jack//继承父类father的getname()方法 console.log(son.getage());//18
多态机制实现
function person(name) { this.name = name; if (typeof this.getname !== "function"){ person.prototype.getname = function () { return this.name; } } if (typeof this.toeat !== "function"){ person.prototype.toeat = function (animal) { console.log( this.getname() + "说去吃饭:"); animal.eat(); } } } function animal(name) { this.name = name; if (typeof this.getname !== "function"){ animal.prototype.getname = function () { return this.name; } } } function cat(name) { animal.call(this,name); if (typeof this.eat !== "function"){ cat.prototype.eat = function () { console.log(this.getname() + "吃鱼"); } } } cat.prototype = new animal(); function dog(name) { animal.call(this,name); if (typeof this.eat !== "function"){ dog.prototype.eat = function () { console.log(this.getname() + "啃骨头"); } } } dog.prototype = new animal(); var person = new person("tom"); person.toeat(new cat("cat"));//tom说去吃饭:cat吃鱼 person.toeat(new dog("dog"));//tom说去吃饭:dog啃骨头
以上这篇老生常谈javascript的面向对象思想就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。