一. this
參考
1.深入淺出妙用 Javascript 中 apply捏题、call涉馅、bind
2.理解 JavaScript 中的 Function.prototype.bind
3.this 關(guān)鍵字
1. apply、call 捻浦、bind有什么作用朱灿,什么區(qū)別
- 作用:三者都可以固定this的值盗扒,避免出現(xiàn)意想不到的情況
- fun.call(thisArg[, arg1[, arg2[, ...]]])
call() 方法調(diào)用一個函數(shù), 其具有一個指定的this值和分別地提供的參數(shù)(參數(shù)的列表) - fun.apply(thisArg, [argsArray])
apply方法的作用與call方法類似侣灶,也是改變this指向褥影,然后再調(diào)用該函數(shù)凡怎。唯一的區(qū)別就是统倒,它接收一個數(shù)組或類數(shù)組對象作為函數(shù)執(zhí)行時的參數(shù) - fun.bind(thisArg[, arg1[, arg2[, ...]]])
創(chuàng)建了一個函數(shù)房匆,當(dāng)這個函數(shù)在被調(diào)用的時候墓猎,它的 this 會被設(shè)置成被傳入第一個值毙沾。
- fun.call(thisArg[, arg1[, arg2[, ...]]])
- 區(qū)別:
1.apply
/call
與bind
bind改變了this值后沒有立即執(zhí)行左胞,而apply和call都是立即執(zhí)行的
var obj = {
a:1
}
var foo = {
getA: function(){
console.log(this.a)
}
}
foo.getA() //undefined
foo.getA.bind(obj)() //1
foo.getA.call(obj) //1
foo.getA.apply(obj) //1
2.apply
和call
apply的第二個參數(shù)是數(shù)組或類數(shù)組對象烤宙,call接受的則是若干個參數(shù)
var arr = [1,2,3,4,9]
console.log(Math.max.apply(Math,arr)) //9
console.log(Math.max.call(Math,1,2,3,4,9))//9
2.以下代碼輸出?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func //john對象添加sayHi方法,方法為func
john.sayHi() //"John: hi!" 執(zhí)行,此時this為john
3.以下代碼輸出?
func() //[object Window] 全局作用域下函數(shù)拐云,this綁定為全局對象
function func() {
alert(this)
}
4.以下代碼輸出?
document.addEventListener('click', function(e){
console.log(this); //document 在事件處理程序中this代表事件源對象
setTimeout(function(){
console.log(this); //window setTimeout函數(shù)始終是在全局作用域下調(diào)用的叉瘩,所以this在非嚴(yán)格模式下指向window
}, 200);
}, false);
5.以下代碼輸出?
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
//John call方法將func的this指定為john對象薇缅,所以this.firstName就是"John"了
6.以下代碼有什么問題泳桦,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么$btn而并非module蓬痒,不能調(diào)用module下的showMsg方法
this.showMsg();
})
},
showMsg: function(){
console.log('沒什么');
}
}
//修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this)
this.showMsg();
}.bind(this))
},
showMsg: function(){
console.log('沒什么');
}
}
二.原型鏈
1.有如下代碼,解釋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("haha")
p.sayName();
//1.定義Person構(gòu)造函數(shù)库正,Person構(gòu)造函數(shù)自帶prototype屬性
//2.prototype屬性中有constructor屬性褥符,指向構(gòu)造函數(shù)
//3.每個構(gòu)造函數(shù)的實例都有__proto__屬性喷楣,指向構(gòu)造函數(shù)的prototype屬性
2.上例中抡蛙,對對象 p可以這樣調(diào)用 p.toString()。toString是哪里來的? 畫出原型圖?并解釋什么是原型鏈捣炬。
如圖示,Person構(gòu)造函數(shù)中沒有toString()方法灭美,所以繼續(xù)在其原型中查找届腐,也沒有犁苏,所以Person.prototype的原型围详,即Object.prototype中查找,然后找到了對象原型中的toString()方法
對象的屬性和方法袁勺,有可能是定義在自身期丰,也有可能是定義在它的原型對象咐汞。由于原型本身也是對象化撕,又有自己的原型植阴,所以形成了一條原型鏈(prototype chain)原文鏈接
3.對String做擴(kuò)展掠手,實現(xiàn)如下方式獲取字符串中頻率最高的字符
String.prototype.getMostOften = function(){
var i, obj = {}
var textSplit = this.split('')
for(i= 0; i<this.length; i++){
if(textSplit[i] in obj){
obj[textSplit[i]]+=1
}else{
obj[textSplit[i]]=1
}
}
var index=0,max
for(key in obj){
if(obj[key] > index){
max = key
index = obj[key]
}
}
return max
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因為d 出現(xiàn)了5次
4.instanceof有什么作用?內(nèi)部邏輯是如何實現(xiàn)的灸拍?
- instanceof判斷對象是否為某個構(gòu)造函數(shù)的實例混槐;
- 內(nèi)部邏輯:判斷構(gòu)造函數(shù)的原型是否在對象的原型鏈上声登,在就返回true悯嗓,反之false
//例
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
var p = new Person("haha")
console.log(p instanceof Person) //true
console.log(p instanceof Object) //true
三.繼承
1.繼承有什么作用?
繼承是指一個對象可以直接使用另一個對象的屬性和方法绅作,繼承提高了代碼復(fù)用性俄认,減少重復(fù)勞動
2.下面兩種寫法有什么區(qū)別?
方法1的實例之間屬性和方法都是獨立的眯杏,共用的屬性和方法不能共享岂贩,同時也浪費資源
方法2的實例之間printName方法是共享的
//方法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);
3.Object.create 有什么作用萎津?兼容性如何锉屈?
Object.create(proto, [ propertiesObject ])
:創(chuàng)建一個對象颈渊,使其原型為傳入的第一個參數(shù)
兼容性:IE 9+
4.hasOwnProperty有什么作用俊嗽? 如何使用绍豁?
hasOwnPerperty
是Object.prototype
的一個方法竹揍,可以判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性鬼佣,hasOwnProperty
是JavaScript中唯一一個處理屬性但是不查找原型鏈的函數(shù)
function Person(name, sex){
this.name = name
this.sex = sex
this.printSex = function(){
console.log(this.sex)
}
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('小明', 27);
console.log(p1.hasOwnProperty('printSex')) //true
console.log(p1.hasOwnProperty('printName')) //false
5.如下代碼中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //這里的call 用于繼承Person的屬性
this.age = age;
}
//在實例化后male里面就可以獲取到name,sex屬性
var male1 = new Male('xiaoming','男',12)
console.log(male1.name,male1.sex,male1.age) //xiaoming 男 12
6.補全代碼晌纫,實現(xiàn)繼承
function Person(name, sex){
this.name = name
this.sex = sex
}
Person.prototype.getName = function(){
console.log(this.name)
};
function Male(name, sex, age){
Person.bind(this)(name,sex)
this.age = age
}
var _prototype = Object.create(Person.prototype)
_prototype.constructor = Male
Male.prototype = _prototype
Male.prototype.getAge = function(){
console.log(this.age)
};
var ruoyu = new Male('ruoyu', '男', 27);
ruoyu.getName();//ruoyu