this 相關問題
問題1: apply菲盾、call 、bind有什么作用全谤,什么區(qū)別
**apply 和 call **
在 JavaScript 中寨典,call 和 apply 都是為了改變某個函數(shù)運行時的上下文(context)而存在的,換句話說想虎,就是為了改變函數(shù)體內(nèi)部 this 的指向卦尊。它們的作用都是一樣的,就是傳遞的參數(shù)不一樣舌厨。
apply 接受2個參數(shù)岂却,第一個參數(shù)指定了函數(shù)體內(nèi)this對象的指向,第二個參數(shù)為數(shù)組或者一個類數(shù)組裙椭,而call則作為call的參數(shù)傳入(從第二個參數(shù)開始)躏哩,如果call方法沒有參數(shù),或者參數(shù)為null或undefined揉燃,則等同于指向全局對象
func.call(this,3,4,5)
func.apply(this.[3,4,5])
所以震庭,一般當參數(shù)數(shù)量固定的時候用call不固定時用apply
bind
bind() 方法與 apply 和 call 很相似,也是可以改變函數(shù)體內(nèi) this 的指向你雌。
MDN的解釋是:bind()方法會創(chuàng)建一個新函數(shù),稱為綁定函數(shù),當調(diào)用這個綁定函數(shù)時婿崭,綁定函數(shù)會以創(chuàng)建它時傳入 bind()方法的第一個參數(shù)作為 this拨拓,傳入 bind() 方法的第二個以及以后的參數(shù)加上綁定函數(shù)運行時本身的參數(shù)按照順序作為原函數(shù)的參數(shù)來調(diào)用原函數(shù)。
var func = function(){
console.log(this.x);
console.log(arguments);
}
func(); // undefined, {}
var obj = {
x: 2
}
var bar = func.bind(obj,1);
bar(); // 2 , {'0':1}
總結(jié)
- apply 氓栈、 call 渣磷、bind 三者都是用來改變函數(shù)的this對象的指向的;
- apply 授瘦、 call 醋界、bind 三者第一個參數(shù)都是this要指向的對象,也就是想指定的上下文提完;
- apply 形纺、 call 、bind 三者都可以利用后續(xù)參數(shù)傳參徒欣;
- bind 是返回對應函數(shù)逐样,便于稍后調(diào)用;apply 打肝、call 則是立即調(diào)用 脂新。
問題2: 以下代碼輸出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()//窗口彈出"John:'hi'"
//利用轉(zhuǎn)化代碼(下同) john.sayHi()相當于john.sayHi.call(john),this指向john
問題3: 下面代碼輸出什么,為什么
func()
function func() {
alert(this)
} //窗口彈出“window”
//func() 可以簡寫為fun.call(undefined),call方法參數(shù)為null或undefined粗梭,則等同于指向全局對象
問題4: 下面代碼輸出什么争便,為什么
document.addEventListener('click', function(e){
console.log(this);//輸出“document”,this指向調(diào)用該函數(shù)的document節(jié)點
setTimeout(function(){
console.log(this);//輸出“Window”,setTimeout函數(shù)中的this指向全局對象
}, 200);
}, false);
問題5: 下面代碼輸出什么断医,為什么
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) //窗口彈出“John”滞乙,this指向john對象
問題6: 以下代碼有什么問題,如何修改
var module= {
bind: function(){
var _this = this //修改部分
$btn.on('click', function(){
console.log(this) //this指向全局對象孩锡,window
_this.showMsg();//修改部分
})
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈相關問題
問題7:有如下代碼酷宵,解釋Person、 prototype躬窜、proto浇垦、p、constructor之間的關聯(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 是Person的一個實例男韧,Person的prototype相當于由其構(gòu)造的實例的屬性方法的公共容器,p的proto指向Person的prototype默垄,Person的prototype里的proto指向Object的prototype此虑,Person的prototype里的constructor既是Person本身
問題8: 上例中,對對象 p可以這樣調(diào)用 p.toString()口锭。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈朦前。
在js中介杆,一切皆對象,每個對象都有一個指向它的原型的的內(nèi)部鏈接(此鏈接還沒有規(guī)范的訪問方式韭寸,一般用__proro__代替),這個原型也有自己的原型春哨,直到每個對象的原型為null為止,這就是原型鏈恩伺。toString()可以通過p.__proro__(指向Person.prototype).__proro__(指向Object.prototype)找到這個方法赴背,所以p可以調(diào)用toString()
問題9:對String做擴展,實現(xiàn)如下方式獲取字符串中頻率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
String.prototype.getMostOften=function(){
var obj = {}
for(var i = 0,j;i<this.length;i++){
j = this[i]
if(obj[j]){
obj[j]++
}else{
obj[j] = 1
}
}
var max=0
var key=0
for(var k in obj){
if(obj[k]>max){
max = obj[k]
key = k
}
}
return key
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
問題10: instanceOf有什么作用晶渠?內(nèi)部邏輯是如何實現(xiàn)的凰荚?
instanceof 運算符用來測試一個對象在其原型鏈中是否存在一個構(gòu)造函數(shù)的 prototype 屬性。instanceOf會判斷對象的.proto是否等于構(gòu)造函數(shù)的原型褒脯,如果不等便瑟,再判斷對象的proto.__proto__;直到null,如果都不等憨颠,則對象不是構(gòu)造函數(shù)的實例胳徽。
繼承相關問題
問題11:繼承有什么作用?
JavaScript 對象有一個指向一個原型對象的鏈。當試圖訪問一個對象的屬性或方法時爽彤,它不僅僅在該對象上搜尋养盗,還會搜尋該對象的原型,以及該對象的原型的原型适篙,依此層層向上搜索往核,直到找到一個名字匹配的屬性或到達原型鏈的末尾。這樣可以實現(xiàn)代碼重用嚷节,節(jié)省內(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的printName()放在People的實例對象中硫痰,無法通過原型鏈來繼承調(diào)用衩婚,方法2中的printName()放在People的prototype中,可以通過原型鏈來繼承效斑、調(diào)用非春,從而節(jié)省內(nèi)存。
問題13: Object.create 有什么作用缓屠?兼容性如何奇昙?
Object.create() 方法使用指定的原型對象和其屬性創(chuàng)建了一個新的對象。
用法:
function inherit(superType, subType){
var _prototype = Object.create(superType.prototype);
_prototype.constructor = subType;
subType.prototype = _prototype;
}
兼容性:
問題14: hasOwnProperty有什么作用敌完? 如何使用储耐?
hasOwnPerperty是Object.prototype的一個方法,可以判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性滨溉。
m.hasOwnProperty('name'); // true
m.hasOwnProperty('printName'); // false
Male.prototype.hasOwnProperty('printAge'); // true
問題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 的作用是將執(zhí)行上下文(context)的環(huán)境切換到Person下什湘,也就是將Person的屬性賦值給Male
問題16: 補全代碼长赞,實現(xiàn)繼承
function Person(name, age){
this.name = name
this.age = age
}
Person.prototype.getName = function(){
console.log('my name is'+ this.name)
};
function Male(name, sex, age){
Person.call(this,name,age)
this.sex = sex
}
Male.prototype =Object.create(Person.prototype)
Male.prototype.constructor = Male
Male.prototype.getAge = function(){
console.log('my age is '+this.age)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.getName();