加入收藏 | 设为首页 | 会员中心 | 我要投稿 开发网_开封站长网 (http://www.0378zz.com/)- 科技、AI行业应用、媒体智能、低代码、办公协同!
当前位置: 首页 > 教程 > 正文

畅聊JavaScript的面向对象思想

发布时间:2021-11-15 11:59:14 所属栏目:教程 来源:互联网
导读:面向对象的三大基本特性 封装(把相关的信息(无论数据或方法)存储在对象中的能力) 继承(由另一个类(或多个类)得来类的属性和方法的能力) 多态(一个对象在不同情况下的多种形态) 定义类或对象 第一种:基于Object对象 var person = new Object(); person.n

面向对象的三大基本特性
 
封装(把相关的信息(无论数据或方法)存储在对象中的能力)
 
继承(由另一个类(或多个类)得来类的属性和方法的能力)
 
多态(一个对象在不同情况下的多种形态)
 
定义类或对象
 
第一种:基于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啃骨头

(编辑:开发网_开封站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读