對象_原型_原型鏈_繼承

1、OOP 指什么?有哪些特性?

OOP是object oriented programming - 面向?qū)ο缶幊痰目s寫。 它具有三大特性: 封裝、繼承、多態(tài)。

  1. 封裝:隱藏對象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對外公開接口
  2. 繼承:子類能繼承父類的屬性和方法
    子類能添加新的屬性和方法,還能重寫父類的屬性和方法
  3. 多態(tài):指同一個(gè)實(shí)體同時(shí)具有多種形式,同一操作作用于不同對象,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。

在面向?qū)ο蟪绦蛟O(shè)計(jì)中有兩個(gè)重要概念

  1. 類:類是對現(xiàn)實(shí)生活中一類具有共同特征的事物的抽象

  2. 對象:對象是類的實(shí)例,對象包含屬性和方法,屬性是需要記憶的信息,方法是對象能夠提供的服務(wù)。

2、如何通過構(gòu)造函數(shù)的方式創(chuàng)建一個(gè)擁有屬性和方法的對象?

屬性可以通過this.xxx = xxx的方式直接賦值,方法可以通過this.prototype.xxx = function(){}的方式創(chuàng)建

//定義構(gòu)造函數(shù),默認(rèn)命名第一個(gè)字母為大寫
function People(name,age){
    this.name = name
    this.age = age
}
people.prototype.slogan = function(){
    console.log(this.name + ' is ' + this.age + ' years old ')     //jirengu is 30 years old
}
//使用new操作符進(jìn)行實(shí)例化
var people = new Peoole('aaa',30)
people.slogan()   

3、prototype 是什么?有什么特性

  • JavaScript的每個(gè)對象都繼承另一個(gè)對象,后者稱為“原型”(prototype)對象。只有null除外,它沒有自己的原型對象。
  • 原型對象上的所有屬性和方法,都能被派生對象共享。
  • 通過構(gòu)造函數(shù)生成實(shí)例對象時(shí),會(huì)自動(dòng)為實(shí)例對象分配原型對象。每一個(gè)構(gòu)造函數(shù)都有一個(gè)prototype 屬性,這個(gè)屬性就是實(shí)例對象的原型對象。
  • prototype里的屬性一旦更改,其實(shí)例內(nèi)也將發(fā)生變化

在JavaScript中,所有的對象都是基于 Object;
所有的對象都繼承了Object.prototype的屬性和方法,它們可以被覆蓋(除了以null為原型的對象,如 Object.create(null))。例如,新的構(gòu)造函數(shù)的原型覆蓋原來的構(gòu)造函數(shù)的原型,提供它們自己的 toString() 方法.。對象的原型的改變會(huì)傳播到所有對象上,除非這些屬性和方法被其他對原型鏈更里層的改動(dòng)所覆蓋。
Object.prototype.constructor 用于創(chuàng)建一個(gè)對象的原型。
Object.prototype.proto 指向當(dāng)對象被實(shí)例化的時(shí)候,用作原型的對象。

4、畫出如下代碼的原型圖

function People (name){
  this.name = name;
  this.sayName = function(){
    console.log('my name is:' + this.name);
  }
}

People.prototype.walk = function(){
  console.log(this.name + ' is walking');  
}

var p1 = new People('aaa');
var p2 = new People('bbb');
原型圖

原型鏈相關(guān)問題

問題7:有如下代碼,解釋Person、 prototype、proto、p、constructor之間的關(guān)聯(lián)。

function Person(name){
    this.name = name;
}
Person.prototype.sayName = function(){
    console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
p._proto_ === Person.prototype   //ture,p是Person的實(shí)例對象,自動(dòng)獲得一個(gè)_proto_對象
Preson.prototype.constructor === Person  //ture

問題8: 上例中,對對象 p可以這樣調(diào)用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈。

原型圖

對象P是沒有toString這個(gè)方法的,但是它有一個(gè)__proto__屬性是指向Person.prototype,Person.prototype中也沒有這個(gè)方法就沿著Person.prototype中的__proto__繼續(xù)找,到了Object.prototype中就有了toString的方法,就可以調(diào)用了。這樣沿著__proto__的“鏈”就是原型鏈。

問題9:對String做擴(kuò)展,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符

String.prototype.getMostOften = function(){
    var str = {}
    var max = 0 
    var max_key = ''

    for(var i = 0; i<this.length ;i++){
        var key = this[i]
        if(!str[key]){
            str[key] = 1
        }else{
            str[key]++
        }
    }
    for(key in str){
        if(str[key]>max){
            max = str[key]
            max_key = key
        }
    }
    return max_key
} 

var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次

問題10: instanceOf有什么作用?內(nèi)部邏輯是如何實(shí)現(xiàn)的?

instanceOf用來判斷對象是否是另一個(gè)的對象的實(shí)例,并返回布爾值。

內(nèi)部邏輯:順著對象的原型連一直往上找,若原型鏈上的某一個(gè)__proto__指向了構(gòu)造函數(shù)的prototype則返回true,找完了原型鏈也找不到則返回false。

Object.prototype.instanceOf = function(obj1,obj2){
        var obj1 = obj1.__proto__;
        while(obj1.__proto__){
          if(obj1 === obj2.prototype){
                   return true;
          }else{
              obj1 = obj1.__proto__;
             }
                return false;
        }

繼承相關(guān)問題

問題11:繼承有什么作用?

繼承是指一個(gè)對象直接使用另一個(gè)對象的屬性和方法,提高重用性,減少代碼內(nèi)存

問題12: 下面兩種寫法有什么區(qū)別?

//方法1
function People(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName = function(){
        console.log(this.name);
    }
}
var p1 = new People('饑人谷', 2)

//方法2
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('若愚', 27);

方法1:是將所有的屬性和方法都寫在構(gòu)造函數(shù)中,每次新建對象都要?jiǎng)?chuàng)建一個(gè)printName函數(shù),會(huì)造成很大的內(nèi)存浪費(fèi)。

方法2:把printName函數(shù)寫在原型鏈上,新建對象可以共享這個(gè)方法,節(jié)省內(nèi)存。

問題13: Object.create 有什么作用?兼容性如何?

Object.create() 方法創(chuàng)建一個(gè)擁有指定原型和若干個(gè)指定屬性的對象。Object.create是在ES5中規(guī)定的,IE9以下無效。

問題14: hasOwnProperty有什么作用? 如何使用?

hasOwnPerperty是Object.prototype的一個(gè)方法,可以判斷一個(gè)對象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JavaScript中唯一一個(gè)處理屬性但是不查找原型鏈的函數(shù)。
用法

obj.hasOwnPerperty('key')    // true or false;

問題15:如下代碼中call的作用是什么?

function Person(name, sex){
    this.name = name;
    this.sex = sex;
}
function Male(name, sex, age){
    Person.call(this, name, sex);    //這里的 call 有什么作用?
    this.age = age;
}

調(diào)用Person函數(shù),使Male函數(shù)能夠執(zhí)行Person上的初始化代碼,實(shí)現(xiàn)構(gòu)造函數(shù)繼承,并且使Person執(zhí)行時(shí)的this指向Male

問題16: 補(bǔ)全代碼,實(shí)現(xiàn)繼承

function Person(name, sex){
    this.name = name
    this.sex = sex
}
Person.prototype.getName = function(){
    console.log('my name is '+ this.name)
};    


function Male(name, sex, age){
    Person.call(this,name,sex)
    this.age = age
}
Male.prototype = Object.create(Person.prototype)
Male.prototype.constructor = Male

Male.prototype.printName = function(){
    console.log(this.name)
}
Male.prototype.getAge = function(){
    console.log('age is'+ this.age)
};

var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容