this
apply、call 、bind有什么作用,什么區別?
-
apply() 方法調用一個函數, 其具有一個指定的this值,以及作為一個數組(或類似數組的對象)提供的參數。
語法:fun.apply(thisArg, [argsArray]) thisArg: 在 fun 函數運行時指定的 this 值。如果這個函數處于非嚴格模式下,則指定為 null 或 undefined 時會自動指向全局對象。 argsArray: 一個數組或者類數組對象,其中的數組元素將作為單獨的參數傳給 fun 函數。
call()方法和apply()方法類似,只有一個區別,計算call()方法接收若干個參數的列表,而apply()方法接收的是一個包含多個參數的數組。
-
bind()方法創建一個新的函數, 當被調用時,將其this關鍵字設置為提供的值,在調用新函數時,在任何提供之前提供一個給定的參數序列。
語法:fun.bind(thisArg[, arg1[, arg2[, ...]]]) thisArg 當綁定函數被調用時,該參數會作為原函數運行時的 this 指向。當使用new 操作符調用綁定函數時, 該參數無效。 arg1, arg2, ... 當綁定函數被調用時,這些參數將置于實參之前傳遞給被綁定的方法。 返回值 返回由指定的this值和初始化參數改造的原函數拷貝
以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() // John: hi!
// this為執行上下文,當一個函數作為對象的方法調用時,this默認指向這個對象
下面代碼輸出什么,為什么?
func() // [object Window]
function func() {
alert(this)
}
// 當直接調用一個函數時,相當于執行window.func()所以this指向window對象
下面代碼輸出什么?
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
// 輸出:#document 、 Window{}
// 第一個:事件中的this默認指向綁定這個事件的對象。
// 第二個:setTimeout的執行函數中的this默認指向window對象
下面代碼輸出什么,why?
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) // Jojn
// call方法用于在函數運行時指定this指,因此執行以上代碼時this指向john對象
以下代碼有什么問題,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指$btn對象
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
// 在事件處理函數中this指向$btn,而$btn沒有showMsg()方法
// 修改:將外部this保存到一個變量中
var module= {
bind: function(){
var self = this
$btn.on('click', function(){
console.log(this)
self.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈
有如下代碼,解釋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(); // 'My name is: 若愚'
// Person是一個函數,它擁有一個prototype屬性,這個屬性指向一個對象,而這個對象擁有一個
constructor屬性,這個屬性指向Person函數
// 當Person作為構造函數調用時,會先初始化一個對象,將this指向這個對象,并將它的__proto__屬性指
向Person.prototype,因此p.name === "若愚",p.sayName() === Person.prototype.sayName()
上例中,對對象 p可以這樣調用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈。
- toString來自Object.prototype。如圖:

- 如上圖所示,當在Person的原型找不到某個方法時,就會沿著它的__proto__逐層向上,直到找到或__proto__屬性為空為止,這個__proto__屬性組成的鏈,就是原型鏈
對String做擴展,實現如下方式獲取字符串中頻率最高的字符
String.prototype.getMostOften = function() {
var obj = {}
var strArr = this.split('')
strArr.forEach(function(i) {
if (obj[i]) {
obj[i]++
} else {
obj[i] = 1
}
})
var max = 0, maxStr
for (var x in obj) {
if (obj[x] > max) {
maxStr = x
max = obj[x]
}
}
return maxStr
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d
instanceOf有什么作用?內部邏輯是如何實現的?
- instanceof用于判斷一個對象的類型,那么它的判斷規則是什么?
- Instanceof運算符的第一個變量一般是一個對象,暫時稱為A;第二個變量一般是一個函數,暫時稱為B。
- Instanceof的判斷規則是:沿著A的__proto__這條線來找,同時沿著B的prototype這條線來找,如果兩條線能找到同一個引用,即同一個對象,那么就返回true。如果找到終點還未重合,則返回false。
繼承
繼承有什么作用?
- 繼承關系是傳遞的。若類C繼承類B,類B繼承類A,則類C既有從類B那里繼承下來的屬性與方法,也有從類A那里繼承下來的屬性與方法,還可以有自己新定義的屬性和方法。繼承來的屬性和方法盡管是隱式的,但仍是類C的屬性和方法。繼承是在一些比較一般的類的基礎上構造、建立和擴充新類的最有效的手段。
- 繼承提供了軟件復用功能。若類B繼承類A,那么建立類B時只需要再描述與基類(類A)不同的少量特征(數據成員和成員方法)即可。這種做法能減小代碼和數據的冗余度,大大增加程序的重用性。
- 繼承通過增強一致性來減少模塊間的接口和界面,大大增加了程序的易維護性。
下面兩種寫法有什么區別?
//方法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.prototype.printName方法
方法2大大節省了內存
Object.create 有什么作用?兼容性如何?
-
Object.create() 方法會使用指定的原型對象及其屬性去創建一個新的對象。兼容ie9及以上瀏覽器
var p1 = Object.create(xxx.prototype) 相當于: var fn = {} fn.__proto__ = xxx.prototype var p1 = fn
hasOwnProperty有什么作用? 如何使用?
-
hasOwnProperty() 方法會返回一個布爾值,指示對象是否具有指定的屬性作為自身(不繼承)屬性。
遍歷一個對象所有自身屬性: var buz = { fog: 'stack' }; for (var name in buz) { if (buz.hasOwnProperty(name)) { alert("this is fog (" + name + ") for sure. Value: " + buz[name]); } }
如下代碼中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex);
//調用Person函數,并把它的this變為Male函數的this,用此方法可實現對Person實例屬性的繼承
this.age = age;
}
補全代碼,實現繼承
function Person(name, sex){
this.name = name
this.sex = sex
}
Person.prototype.printName = function(){
console.log(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.getAge = function(){
console.log(this.age)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();