this 相关问题
1: apply、call 、bind有什么作用,什么区别?
在JS中,这三者都是用来改变函数的this对象的指向,相似点:
1.都是用来改变函数的this对象的指向的。
2.第一个参数都是this要指向的对象。
3.都可以利用后续参数传参。
不同之处:bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。
举个例子:
var obj = {
x: 81,
};
var foo = {
getX: function() {
return this.x;
}
}
console.log(foo.getX.bind(obj)()); //81
console.log(foo.getX.call(obj)); //81
console.log(foo.getX.apply(obj)); //81
三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。
也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。
对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。例如,有一个函数定义如下:
var func = function(arg1, arg2) {
};
就可以通过如下方式来调用:
func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])
其中 this 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时用 call 。
而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数。
2: 以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() //弹出,John: hi!
3: 下面代码输出什么,为什么
func() //弹出window对象,因为在全局作用域下调用,this指向全局对象
function func() {
alert(this)
}
4:下面代码输出什么
document.addEventListener('click', function(e){
//绑定事件中的this指向触发事件的元素对象,这里指的是document对象
console.log(this);
setTimeout(function(){
//setTimeout中的this指向全局对象window,所以输出window对象
console.log(this);
}, 200);
}, false);
上面代码输出document元素对象和window对象
5:下面代码输出什么,为什么
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john) //John
//call方法将func方法的this指向变为john对象
6: 以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) /绑定事件中的this指向触发事件的元素对象,这里是$btn对象
this.showMsg(); //$btn元素没有showMsg方法
})
},
showMsg: function(){
console.log('徐国军');
}
}
修改:
var module= {
bind: function(){
var _this = this; //保存this,this指向当前对象
$btn.on('click', function(){
console.log(this)
_this.showMsg();
})
},
showMsg: function(){
console.log('xuguojun');
}
}
原型链相关问题
7:有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。
function Person(name){
this.name = name;
}
Person.prototype.sayName = function(){
console.log('My name is :' + this.name);
}
------------------------------------------------------------------------------------------
Person.prototype = p._proto_,Person.prototype.constructor = Person
var p = new Person("徐国军")
p.sayName();//输出My name is :徐国军
8: 上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
9:对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
------------------------------------------------------------------------------------------
String.prototype.getMostOften = function() {
var str = {};
var letter;
for(var i = 0; i < this.length; i++){
letter = this[i];
if(!str[letter]){
str[letter] = 1;
}
else{
str[letter] ++;
}
}
var max = 0;
var newStr;
for(var key in str){
if(str[key] > max){
max = str[key];
newStr = key;
}
}
return newStr;
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
10: instanceOf有什么作用?内部逻辑是如何实现的?
instanceof运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。即判断是不是一个对象的实例,是返回 true,不是返回false。
var arr = [1,2,3],
obj = {name:'xuguojun'};
arr instanceof Array //true
//内部逻辑为看实例的 __proto__ 是否等于构造函数的 prototype 。
arr.__proto__ === Array.prototype //true
//如果为 true ,则返回结果 true
arr instanceof Object //true
//内部逻辑为看实例的 __proto__ 是否为构造函数的 prototype 原型
arr.__proto__ === Object.prototype //false
//如果为 false ,则继续看下一层的 __proto__
arr.__proto__.__proto__ === Object.prototype //true
//如果为 true ,则返回结果 true
obj instanceof Array //false
//内部逻辑为看实例的 __proto__ 是否为构造函数的 prototype 原型
obj.__proto__ === Array.prototype //false
//如果为 false ,则继续看下一层的 __proto__
obj.__proto__.__proto__ === Array.prototype //false
//如果到最深一层的 __proto__ (最深一层为null)比较还是不相等,则返回 false
11:继承有什么作用?
继承就是子类拥有父类的属性和方法。
作用:继承划分了类的层次性,父类代表的是更一般、更泛化的类,而子类则是更为具体、更为细化;继承是实现代码重用、扩展软件功能的重要手段。子类中与父类完全相同的属性和方法不必重写,因为通过继承,子类会拥有父类的属性和方法,不需要重新去写这些重复的代码,提高了代码的重用性。而只需写出新增或改写的内容,直接给子类添加新的属性和方法,子类就会拥有这些属性和方法,表现出多态化,而父类不会被“污染”,提高了代码的独立性。这就是说子类可以复用父类的内容,不必一切从零开始。
12: 下面两种写法有什么区别?
//方法1
function People(name, sex){
this.name = name;
this.sex = sex;
this.printName = function(){
console.log(this.name);
}
}
var p1 = new People('xuguojun', 2)
//这种形式创建的p1本身有name、sex属性和printName方法
//方法2
function Person(name, sex){
this.name = name;
this.sex = sex;
}
Person.prototype.printName = function(){
console.log(this.name);
}
var p1 = new Person('xuguojun', 25);
//这种形式创建的p1本身有name、sex属性,但没有printName方法,但p1能够通过原型链调用Person原型的printName方法。
13: Object.create 有什么作用?兼容性如何?
作用:Object.create() 方法使用指定的原型对象和其属性创建了一个新的对象。
语法:
Object.create(proto, [ propertiesObject ])
参数
proto
一个对象,应该是新创建的对象的原型。
propertiesObject
可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()
的第二个参数一样)。注意:该参数对象不能是 undefined
,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。
浏览器兼容性
var me = {
name: "cg",
sayName: function(){
console.log("My name is " + this.name);
}
}
var p = Object.create(me)
//以 me 对象为原型,创建了实例 p
p.__proto__ === me //true
14: hasOwnProperty有什么作用? 如何使用?
hasOwnProperty() 方法会返回一个布尔值,判断一个属性是否是自身的属性,返回 true 或 false
示例:
function People(name){
this.name = name
}
People.prototype.sayName = function(){
console.log("My name is " + this.name);
}
var p = new People("hi")
p.hasOwnProperty("name") //true
//name 是 p 自己的属性,所以返回true
p.hasOwnProperty("sayName") //false
//sayName 是 p 的原型 __proto__ 里的属性,不是自己的属性,所以返回false
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;
}
//作用:在Male函数中,调用Person函数,指定Person方法中的this为Male,使Male函数能够执行Person上的初始化代码,实现构造函数继承。
16: 补全代码,实现继承
function Person(name, sex){
// todo ...
}
Person.prototype.getName = function(){
// todo ...
};
function Male(name, sex, age){
//todo ...
}
//todo ...
Male.prototype.getAge = function(){
//todo ...
};
var ruoyu = new Male('徐国军', '男', 27);
ruoyu.printName();
补全代码:
function Person(name, sex){
// todo ...
this.name = name;
this.sex = sex;
}
Person.prototype.getName = function(){
// todo ...
console.log(this.name);
};
function Male(name, sex, age){
//todo ...
Person.call(this,name,sex);
this.age = age;
}
//todo ...
Male.prototype = Object.create(Person.prototype);
Male.prototype.constructor = Male;
Male.prototype.getAge = function(){
//todo ...
console.log(this.age);
};
var ruoyu = new Male('xuguojun', '男', 25);
ruoyu.getName();