由于運(yùn)行期綁定的特性,JavaScript 中的 this 含義非常多,它可以是全局對(duì)象、當(dāng)前對(duì)象或者任意對(duì)象,這完全取決于函數(shù)的調(diào)用方式。
隨著函數(shù)使用場(chǎng)合的不同,this的值會(huì)發(fā)生變化。但是有一個(gè)總的原則,<strong>那就是this指的是,調(diào)用函數(shù)的那個(gè)對(duì)象。</strong>
什么是this?
方老師講的很好,這邊我就不重復(fù)了
https://zhuanlan.zhihu.com/p/23804247?refer=study-fe
什么是apply,call?
語(yǔ)法:call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定義:參數(shù) thisObj 可選項(xiàng)。將被用作當(dāng)前對(duì)象的對(duì)象。 arg1, arg2, , argN 可選項(xiàng)。將被傳遞方法參數(shù)序列。
說(shuō)明 :
call 方法可以用來(lái)代替另一個(gè)對(duì)象調(diào)用一個(gè)方法。call 方法可將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對(duì)象。
如果沒(méi)有提供 thisObj 參數(shù),那么 Global 對(duì)象被用作thisObj。說(shuō)明白一點(diǎn)其實(shí)就是更改對(duì)象的內(nèi)部指針,即改變對(duì)象的this指向的內(nèi)容。這在面向?qū)ο蟮膉s編程過(guò)程中有時(shí)是很有用的。
語(yǔ)法:apply([thisObj[,argArray]])
定義:應(yīng)用某一對(duì)象的一個(gè)方法,用另一個(gè)對(duì)象替換當(dāng)前對(duì)象。
說(shuō)明:
如果 argArray 不是一個(gè)有效的數(shù)組或者不是 arguments 對(duì)象,那么將導(dǎo)致一個(gè) TypeError。
如果沒(méi)有提供 argArray 和 thisObj 任何一個(gè)參數(shù),那么 Global 對(duì)象將被用作 thisObj, 并且無(wú)法被傳遞任何參數(shù)。
下面是測(cè)試this熟悉程度的題目:
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() //輸出John: hi! this是用john這個(gè)對(duì)象調(diào)用的,所以this===johN.firstName
func()
function func() {
alert(this) //直接調(diào)用函數(shù),obj為window對(duì)象
}
document.addEventListener('click', function(e){
console.log(this); //document調(diào)用addEventListener方法,所以this的obj為document
setTimeout(function(){
console.log(this); //setTimeout內(nèi)調(diào)用匿名函數(shù),obj為window
}, 200);
}, false);
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) //將func中的this對(duì)象設(shè)置為john
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指向$btn的原生DOM
this.showMsg();
})
},
showMsg: function(){
console.log('饑人谷');
}
}
原型鏈相關(guān)問(wèn)題
1.有如下代碼,解釋Person、 prototype、proto、p、constructor之間的關(guān)聯(lián)。
Person是原型,P是Person的實(shí)例,Person的prototype定義了sayName 方法,P根據(jù)proto原型鏈查找sayName方法,Person的prototype方法上constructor指向了Person的地址
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("若愚")
p.sayName();
- 上例中,對(duì)對(duì)象 p可以這樣調(diào)用 p.toString()。toString是哪里來(lái)的? 畫(huà)出原型圖?并解釋什么是原型鏈。

通過(guò)原型鏈查到object原型,里面有toString()方法
3.對(duì)String做擴(kuò)展,實(shí)現(xiàn)如下方式獲取字符串中頻率最高的字符
<script>
String.prototype.getMostOften = function() {
var obj = {},tmp = [0];
for (var i = 0; i < this.length; i++) {
if(obj[this[i]]){
obj[this[i]]++
}
else if(!obj[this[i]]){
obj[this[i]]=1;
}
}
for(var key in obj){
if(obj[key]>tmp[0]){
tmp[0]=obj[key];
tmp.key=key;
}
}
return('出現(xiàn)最多的是:'+tmp.key+' num: '+tmp);
};
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因?yàn)閐 出現(xiàn)了5次
</script>
4.instanceOf有什么作用??jī)?nèi)部邏輯是如何實(shí)現(xiàn)的?
判斷一個(gè)實(shí)例的原型是誰(shuí)
function instanceOf(obj,fn){
var oldpro = obj.__proto__;
while(oldpro){
if(oldpro === fn.prototype){
return true;
}else{
oldpro = oldpro.__proto__;
}
}
return false;
}
繼承相關(guān)問(wèn)題:
1.什么是繼承?繼承有什么用?
概念:繼承是指一個(gè)對(duì)象直接使用另一個(gè)對(duì)象的屬性和方法。
作用:繼承劃分了類的層次性,父類代表的是更一般、更泛化的類,而子類則是更為具體、更為細(xì)化;
繼承是實(shí)現(xiàn)代碼重用、擴(kuò)展軟件功能的重要手段,子類中與父類完全相同的屬性和方法不必重寫(xiě),只需寫(xiě)出新增或改寫(xiě)的內(nèi)容,這就是說(shuō)子類可以復(fù)用父類的內(nèi)容,不必一切從零開(kāi)始。
2.下面兩種寫(xiě)法有什么區(qū)別?
//方法1,直接在原型中寫(xiě)入方法,在創(chuàng)建P1實(shí)例的時(shí)候相當(dāng)于又重新拷貝了一個(gè)printName方法
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('饑人谷', 2)
//方法2,通過(guò)原型鏈創(chuàng)建方法,創(chuàng)建P1實(shí)例的時(shí)候相當(dāng)于借用原型的printName方法
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('若愚', 27);
3.Object.create 有什么作用?兼容性如何?
Object.create創(chuàng)建一個(gè)具有指定原型且可選擇性地包含指定屬性的對(duì)象??梢酝ㄟ^(guò)Object.create()方法實(shí)現(xiàn)類式繼承,如:
Male.prototype = Object.create(Person.prototype);
通過(guò)Object.create()clone了一個(gè)新的prototype,使Male.prototype指向這個(gè)新的prototype,而不是直接將Person.prototype賦值給它,這樣做可以避免當(dāng)我修改Male.prototype的時(shí)候不會(huì)將它的父類Person.prototype也修改了。
4.hasOwnProperty有什么作用? 如何使用?
hasOwnPerperty是Object.prototype的一個(gè)方法,可以判斷一個(gè)對(duì)象是否包含自定義屬性而不是原型鏈上的屬性,hasOwnProperty是JavaScript中唯一一個(gè)處理屬性但是不查找原型鏈的函數(shù)。
5.如下代碼中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //修改this指向的對(duì)象,借用Person的name和sex屬性
this.age = age;
}
6.補(bǔ)全代碼,實(shí)現(xiàn)繼承
function Person(name, sex){
this.name = name;
this.sex = sex;
this.printName=function(){
console.log('Hello, '+name);
}
}
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);
function inherit(superType, subType){ //添加constructor地址,指向Male
var _prototype = Object.create(superType.prototype);
_prototype.constructor = subType;
subType.prototype = _prototype;
}
inherit(Person, Male);
Male.prototype.getAge = function(){
console.log('my age is ' + this.age)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
ruoyu.getName();
ruoyu.getAge();
這道題目能很好的去理解原型鏈,this,和繼承
