this 相关问题
apply、call 、bind有什么作用,什么区别
- apply和call:都是为了改变某个函数运行时的上下文而存在的(就是为了改变函数内部 this的指向)
使用apply或call方法
-
第一个参数为“this”,指向某个想要指向的对象;
-
apply的第二个参数是一个参数数组;
-
call的第二个及其以后的参数都是数组里面的元素(就是说要全部列举出来)
//调用函数并且指定上下文的'this'
function Person(name,age){
this.name = name
this.age = age
}
Person.prototype.sayName=function(){
console.log("my name is "+ this.name+ "My age is " + this.age)
}
//创建一个没有任何方法的对象
var people = {
name:"harry",
age:9
}
var p = new Person("ben",55)
//people对象调用p对象中的方法
p.sayName.call(people)
//"my name is harryMy age is 9"
p.sayName.apply(people)
//"my name is harryMy age is 9"
//使用内置函数
var arr = [1, 0, 2, 4]
console.log(Math.max(...arr) )
//4 //ES6语法,将数组拆分为一个个
console.log( Math.max.apply(null, arr))
//4 //由于无须修改对象,故第一参数为null
bind()--也是改变函数体内this的指向;
bind会创建一个新函数,称为绑定函数,当调用这个函数的时候,绑定函数会以创建它时传入。
bind()方法的第一个参数作为this,传入bind()方法的第二个及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数;
总的来说bind方法和call方法作用一样,只是会生成新的函数,可以自定义调用时间(call/apply方法都是立即调用)
var m = {
"x" : 1
};
function foo(y) {
console.log(this.x + y);
}
foo.apply(m, [5]); //立即执行
foo.call(m, 5); //立即执行
var foo1 = foo.bind(m, 5);
foo1(); //调用bind绑定的foo1
训练
给对象添加方法
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
//给john对象添加sayHi方法为func()
john.sayHi()
//弹出出:"John: hi!"
若无指向,this默认指向window
func()
function func() {
alert(this) // window对象
}
//因为此处的this只是作为普通函数调用,故指向window
监听事件的this
document.addEventListener('click', function(e){
console.log(this); //绑定了click事件的对象(例如按了按钮,此时的this就指那个按钮)
setTimeout(function(){
console.log(this); //this为window,setTimeout的this默认window
}, 200);
}, false);
call绑定this
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) //"John"
//此处给john对象绑定了func方法,故此处的this只目前的对象(john)
对象中this
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么(绑定了click事件的对象)
this.showMsg(); //此处会出错,因为绑定click时间的对象没有(不一定)showMsg方法
})
},
showMsg: function(){
console.log('YQY');
}
}
应该为
var module= {
bind: function(){
_this = this
$btn.on('click', function(){
console.log(this) //this指父对象
_this.showMsg(); //此时运行父对象中的showMsg方法
})
},
原型链相关问题
有如下代码,解释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();
image.png
上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?
image.png- 因为Object函数创建了Person.prototype对象,所以Object.prototype === Person.prototype._proto_。故Person函数的也拥有Object的toString()方法。
原型链: 函数的原型对象constructor默认指向函数本身,原型对象除了有原型属性外,为了实现继承,还有一个原型链指针_proto,该指针指向上一层的原型对象,而上一层的原型对象的结构依然类似,这样利用_proto一直指向Object的原型对象上,而Object的原型对象用Object.prototype._proto_ = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同时也解释了为什么所有的javascript对象都具有Object的基本方法。
对String做扩展,实现如下方式获取字符串中频率最高的字符
String.prototype.getMostOften = function(){
var obj = {}
var max = 0
var maxChar
var str = this
for(var i = 0; i < str.length; i++){
var key = str.charAt(i)
if(obj[key]){
obj[key]++
}else{
obj[key] = 1
}
}
for(var k in obj){
if(max < obj[k]){
max = obj[k];
maxChar = k
}
}
console.log(maxChar +" show up "+ max)
return maxChar
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
instanceOf有什么作用?内部逻辑是如何实现的?
instanceOf可以判断一个对象是不是某个类型的实例。
function isInstanceOf(obj, constructor) {
var __proto__ = obj.__proto__;
do {
if (!__proto__) {
return false
} else if (__proto__ === constructor.prototype) {
return true
}
} while (__proto__ = __proto__.__proto__)
return false
}
console.log(isInstanceOf([1, 2, 3], Array)) //true
console.log(isInstanceOf([1, 2, 3], Object)) //true
console.log(isInstanceOf([1, 2, 3], Function)) //false
继承相关问题
继承有什么作用?
作用:继承可以使一个对象直接使用另一对象的属性和方法,提高代码的可用性。
下面两种写法有什么区别?
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('YQY', 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);
- 方法一:把所有函数属性和方法都绑定在People函数下;
- 方法二:把属性绑定在People函数下,方法绑定在People的原型上;
区别: 方法一效率比较低下,若日后需要添加其他对象共用People的方法时,就要重新写,但若把方法放入原型类,只需要把新的对象承继People的原型中的方法即可。
Object.create 有什么作用?兼容性如何?
- Object.create可以clone一个父类的prototype并传给子类,来实现方法继承。如果直接将Parent.prototype赋给Child.prototype,因为引用关系,修改Child.prototype会改变Parent.prototype,而用Object.create是clone了一个新的prototype,不会产生上述问题。
但需注意,如果对子类添加方法,必须要在修改其prototype之后,以免新方法被覆盖。
Child.prototype=Object.creat(Parent.prototype)
Object.create是ES5的方法,兼容IE9,Edge,Chrome5,Firefox4,Opera11.6,Safari5。
hasOwnProperty有什么作用? 如何使用?
hasOwnProperty 用于判断某个属性是属于实例自己的还是从原型链上继承到的属性。
m.hasOwnProperty('name'); // true
m.hasOwnProperty('printName'); // false
Male.prototype.hasOwnProperty('printAge'); // true
如下代码中call的作用是什么?
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //这里的 call 使Male函数承继Person函数的name,sex属性
this.age = age;
}
实现继承例子
function Person(name, age){
this.name = name
this.age = age
}
Person.prototype.getName = function(){
console.log(this.age)
};
function Male(name, age, sex){
Person.call(this,name, age)
this.sex = sex
}
Male.prototype = Object.create(Person.prototype)
Male.prototype.getSex = function(){
console.log(this.sex)
};
var ruoyu = new Male('YQY', 2, '男');
ruoyu.getName();
ruoyu.getSex()
网友评论