1、OOP 指什么?有哪些特性?
OOP是object oriented programming - 面向?qū)ο缶幊痰目s寫。 它具有三大特性: 封裝、繼承、多態(tài)。
- 封裝:隱藏對象的屬性和實(shí)現(xiàn)細(xì)節(jié),僅對外公開接口
-
繼承:子類能繼承父類的屬性和方法
子類能添加新的屬性和方法,還能重寫父類的屬性和方法 - 多態(tài):指同一個(gè)實(shí)體同時(shí)具有多種形式,同一操作作用于不同對象,可以有不同的解釋,產(chǎn)生不同的執(zhí)行結(jié)果。
在面向?qū)ο蟪绦蛟O(shè)計(jì)中有兩個(gè)重要概念
類:類是對現(xiàn)實(shí)生活中一類具有共同特征的事物的抽象
對象:對象是類的實(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();