时间:2021-05-18
面向对象的三大基本特性
封装(把相关的信息(无论数据或方法)存储在对象中的能力)
继承(由另一个类(或多个类)得来类的属性和方法的能力)
多态(一个对象在不同情况下的多种形态)
定义类或对象
第一种:基于Object对象
var person = new Object();person.name = "Rose";person.age = 18;person.getName = function () { return this.name;};console.log(person.name);//Roseconsole.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);//Roseconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Roseconsole.log(person2.name);//Jackconsole.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);//Engineerdelete person.job;//删除属性console.log(person.job);//undefined//删除属性后值为undefinedperson.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());//Tomconsole.log(son.getName());//Jack//继承父类getName()方法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());//Tomconsole.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());//Tomconsole.log(fatherB.getJob());//Engineerconsole.log(son.getName());//Jack//继承父类FatherA的getName()方法console.log(son.getJob());//Programmer//继承父类FatherB的getJob()方法console.log(son.getAge());//18apply()方法
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());//Tomconsole.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());//Tomconsole.log(fatherB.getJob());//Engineerconsole.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());//Tomconsole.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());//Tomconsole.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的面向对象思想就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
前言javascript中的this,constructor,prototype,都是老生常谈的问题,深入理解他们的含义至关重要。在这里,我们再来复习一下吧,温
作为java中的一个重要理念,说起面向对象也是老生常谈了。在找资料的时候多是很专业的术语,又或者很多框架的知识点合集,其实大部分人刚看资料的时候是不能理解的。本
老生常谈的配置但是还是需要说明一下EurekaApplication@EnableEurekaServer指定为server端@EnableEurekaServ
本文实例讲述了JavaScript异步操作的几种常见处理方法。分享给大家供大家参考,具体如下:引言js的异步操作,已经是一个老生常谈的话题,关于这个话题的文章随
原文首发于知乎:https://www.zhihu.com/question/41638271/answer/493551513这个问题是最老生常谈的问题,每个