this&原型鏈&繼承 · 問答
this 相關問題
問題1: apply、call 、bind有什麼作用,什麼區別
共同點:都可以改變函式執行的上下文
不同點:
bind()方法會建立一個新的函式, 當被呼叫時,將其this關鍵字設定為提供的值,在呼叫新函式時,在任何提供之前提供一個給定的引數序列。
而call和apply是在函式呼叫時使其具有一個指定的this值,沒有建立新函式。
call和apply的返回值是:指定的this值和引數。
bind的返回值是:指定的this值和初始化引數改造的原函式拷貝。
call和apply的唯一區別就是call()方法接受的是若干個引數的列表,而apply()方法接受的是一個包含多個引數的陣列。
call中的引數需要依次傳入
例如:fn.call(context, param1, param2, param3)
apply中的引數則是以陣列的形式傳入
例如:fn.apply(context, [param1, param2, param3])或
var paramArray = [param1, param2, param3];
fn.apply(context, paramArray)
問題2: 以下程式碼輸出什麼?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
會輸出John: hi!
john.sayHi()
形式類似於:
obj.child.method.call(obj.child, p1, p2)
可以轉換為:
john.sayHi().call(john)
所以this.firstName就是john.firstName
問題3: 下面程式碼輸出什麼,為什麼
func()
function func() {
alert(this)
}
會輸出window物件
func()可以轉化為
func.call(undefined)
在瀏覽器中,如果context為undefined或者null那麼預設context為window物件
問題4:下面程式碼輸出什麼
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
點選document物件後,先輸出document物件,兩秒後輸出window物件
首先在事件處理程式中this代表事件源DOM物件
其次在setTimeout(還有setInterval)中,所有this都指向window物件
問題5:下面程式碼輸出什麼,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
會輸出John
func.call(john)指定了func函式的this為john物件
alert( john.firstName )
問題6: 以下程式碼有什麼問題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什麼
this.showMsg();
})
},
showMsg: function(){
console.log('飢人谷');
}
}
bind函式的原意是給按鈕$btn加上監聽,點選後呼叫module的另一個方法showMsg輸出 '飢人谷' 。
但是在jQuery的事件處理程式中this都指向與select相匹配的元素,在這裡的this就是$btn。
修改:
var module= {
bind: function(){
var _this = this;
$btn.on('click', function(){
console.log(_this);
_this.showMsg();
})
},
showMsg: function(){
console.log('飢人谷');
}
}
原型鏈相關問題
問題7:有如下程式碼,解釋Person、 prototype、__proto__、p、constructor之間的關聯。
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
Person是建構函式
p是Person構造的例項
建構函式Person的prototype和例項p的__proto__指向相同
Person.prototype == p.__proto__
Person原型的建構函式指向Person自己
Person.prototype.constructor == Person
問題8: 上例中,物件 p可以這樣呼叫 p.toString()。toString是哪裡來的? 畫出原型圖?並解釋什麼是原型鏈。
首先p發現自己沒有toString()方法,於是p根據其屬性__proto__去原型Person.prototype中找。
發現還是沒有,於是Person.prototype根據其屬性__proto__去Object的原型中找。
發現有toString方法,於是p就可以呼叫toString()方法了。
原型鏈就是當一個物件發現自己沒有要呼叫的屬性或方法時,它會去自己的原型裡去找,若還是沒有就繼續去原型的原型裡找,直到找到這個屬性(或方法)或者當前物件的原型為null了才停止。
問題9:對String做擴充套件,實現如下方式獲取字串中頻率最高的字元
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現了5次
if(!String.hasOwnProperty('getMostOften')){ //先檢查一下原型裡有沒有這個方法
String.prototype.getMostOften = function(){
var array = this.split('');
var mostOften = {};
var mostNum = 0;
var mostItem = '';
for(var i = 0; i<array.length; i++){
if(mostOften.hasOwnProperty(array[i])){
mostOften[array[i]] += 1;
if(mostOften[array[i]]>mostNum){
mostNum = mostOften[array[i]];
mostItem = array[i];
}
}else{
mostOften[array[i]] = 0;
}
}
return mostItem;
}
}
問題10: instanceOf有什麼作用?內部邏輯是如何實現的?
instanceOf可以測試一個物件在其原型鏈中是否存在一個建構函式的 prototype 屬性
內部邏輯
就是沿著這個物件的原型鏈,一個一個去檢視有沒有和這個建構函式的prototype相等的原型,直到到達原型鏈的末尾。
function myInstanceOf(obj, constru){
var objProto = obj.__proto__;
while(objProto !== constru.prototype){
objProto =objProto.__proto__;
if(objProto == null){
return false;
}
}
return true;
}
繼承相關問題
問題11:繼承有什麼作用?
子類可以用父類的屬性和方法(重複使用)
- 共用原型的方法和屬性,節省記憶體
- 區分共用和私用的方法和屬性,構建物件之間合理的結構
問題12: 下面兩種寫法有什麼區別?
//方法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每次建立一個例項都會重新給例項宣告一個新的printName方法
方法2把printName方法放到了Person原型中,這樣每次建立例項,不用重新宣告例項的printName方法
當例項呼叫printName方法時只需去Person的原型裡去呼叫。
問題13: Object.create 有什麼作用?相容性如何?
Object.create() 方法使用指定的原型物件和其屬性建立了一個新的物件。
可以使用Object.create實現類式繼承。
問題14: hasOwnProperty有什麼作用? 如何使用?
hasOwnProperty()可以判斷一個物件是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JavaScript中唯一一個處理屬性但是不查詢原型鏈的函式。
obj.hasOwnProperty(prop)
引數prop
要檢測的屬性字串名稱或者Symbol
返回值
用來判斷某個物件是否含有指定的屬性的Boolean
問題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;
}
這裡call的作用是讓Male類繼承Person類的name和sex屬性
問題16: 補全程式碼,實現繼承
function Person(name, sex){
// todo ...
}
Person.prototype.getName = function(){
// todo ...
};
function Male(name, sex, age){
//todo ...
Person.call(this, name, sex);
}
Male.prototype = Object.create(Person.prototype);
Male.prototype.constructor = Male;
//todo ...
Male.prototype.getAge = function(){
//todo ...
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
相關文章
- JavaScript 原型鏈與繼承問答(第一天)JavaScript原型繼承
- JS原型鏈繼承JS原型繼承
- 原型,繼承——原型繼承原型繼承
- javascript原型鏈及繼承JavaScript原型繼承
- javascript - 繼承與原型鏈JavaScript繼承原型
- JS原型鏈與繼承別再被問倒了JS原型繼承
- 徹底搞懂原型、原型鏈和繼承原型繼承
- 建構函式、原型、原型鏈、繼承函式原型繼承
- 面試題之原型、原型鏈、和繼承面試題原型繼承
- 【機制】JavaScript的原型、原型鏈、繼承JavaScript原型繼承
- 原型、原型鏈、new做了什麼、繼承原型繼承
- 物件、原型鏈、類、繼承【上】物件原型繼承
- 圖解JavaScript原型鏈繼承圖解JavaScript原型繼承
- javascript原型鏈繼承的使用JavaScript原型繼承
- JS的原型鏈和繼承JS原型繼承
- 小議JS原型鏈、繼承JS原型繼承
- Javascript之繼承(原型鏈方式)JavaScript繼承原型
- JS原型鏈、prototype、__proto__、原型鏈繼承詳解JS原型繼承
- 深入理解原型鏈和繼承原型繼承
- javascript基礎-原型鏈與繼承JavaScript原型繼承
- JS中的繼承與原型鏈JS繼承原型
- 白話JavaScript原型鏈和繼承JavaScript原型繼承
- [JavaScript]原型、原型鏈、建構函式與繼承JavaScript原型函式繼承
- 淺談JS物件的建立、原型、原型鏈繼承JS物件原型繼承
- MDN繼承和原型鏈章筆記繼承原型筆記
- 深入理解JavaScript原型鏈與繼承JavaScript原型繼承
- js 原型鏈實現類的繼承JS原型繼承
- 深入淺出JavaScript之原型鏈&繼承JavaScript原型繼承
- 原型和繼承原型繼承
- 物件-原型-繼承物件原型繼承
- JS的物件導向(理解物件,原型,原型鏈,繼承,類)JS物件原型繼承
- js 原型鏈繼承__proto__、prototype簡析JS原型繼承
- 原型鏈實現繼承的6種方式原型繼承
- 深入淺出JavaScript之原型鏈和繼承JavaScript原型繼承
- JS原型繼承和類式繼承JS原型繼承
- Javascript繼承4:潔淨的繼承者—-原型式繼承JavaScript繼承原型
- 【JS面試向】深入原型鏈之class的繼承JS面試原型繼承
- 原型繼承:子類原型繼承