1、apply、call 、bind有什么作用,什么区别?
- apply语法--->
fun.apply(thisArg[, argsArray])
;thisArg是函数fun在运行时指定的this值;[argsArray]是一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数
var value = 100;
function fn(a,b){
console.log(this.value + a + b);
}
fn(1,2);//103
//apply()
var obj = {
value: 200
};
fn.apply(obj,[1,2]);//此时的this是obj,那么value值为200
- call语法--->
fun.call(thisArg[, arg1[, arg2[, ...]]])
;thisArg是函数fun在运行时指定的this值;arg1,arg2是参数列表
var value = 100;
function fn(a,b){
console.log(this.value + a + b);
}
fn(1,2);//103
//call()
var obj = {
value: 200
};
fn.call(obj,1,2);//此时的this是obj,那么value值为200,结果为203
- bind语法--->
fun.bind(thisArg[, arg1[, arg2[, ...]]])
;当绑定函数被调用时,该参数会作为原函数运行时的 this 指向,当使用new操作符调用绑定函数时,该参数无效;arg1, arg2当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法
var obj = {
name: 'Byron',
fn : function(){
console.log(this);
}
};
var obj2 = {
name: 'obj2'
};
var fn2 = obj.fn.bind(obj2);//this指向obj2
fn2();
- 区别:
- call()的第二个参数是一个参数列表,apply()的第二个参数是一个数组或类数组对象
- bind()方法返回的仍然是一个函数,可以不立即执行,还可以在调用的时候再进行传参;而call()和apply()则是立即执行改变了this的函数
2、以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
//对象的方法调用,this指向调用方,输出的结果为John: hi!
3、下面代码输出什么,为什么?
func()
function func() {
alert(this)
}
//函数调用,this指向的是window,输出结果为object Window
4、下面代码输出什么?
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
//第一个this,指向绑定事件源DOM对象,输出结果是#document
//第二个this,指向全局对象window,输出结果是windows
5、下面代码输出什么,why?
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
//call调用,this指向call的第一个参数,这里是john,输出结果是John
6、以下代码有什么问题,如何修改?
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
//这里的this指的是绑定事件的$btn,指不到module,this.showMsg()将不会实现
//修改代码如下
var module= {
bind: function(){
var that = this;
$btn.on('click', function(){
console.log(that);
that.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
7、有如下代码,解释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();
/*关联如下
p是Person的一个实例
p.__proto__ === Person.prototype
p.__proto__.constructor === Person
Person.prototype.constructor === Person
Person.prototype.__proto__ === Object.prototype
Object.prototype.constructor === Object
*/
8、上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链
- toString()是从原型Object里面继承的
-
原型图如下所示:
原型图.png - 原型链--->JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾
9、对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
- 实现代码如下:
//对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
String.prototype.getMostOften = function(){
var rawStr = this.toString(),
length = this.length,
obj = {};
var biggest = {
str: '',
count: 0
};
for(var index = 0; index < length; index++){
var val = rawStr[index];
if(obj[val]){
obj[val] += 1;
}else{
obj[val] = 1;
}
if(obj[val] > biggest.count){
biggest.count = obj[val];
biggest.str = val;
}
}
return biggest;
};
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
10、instanceOf有什么作用?内部逻辑是如何实现的?
- instanceof--->语法:object instanceof constructor,instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上,如果存在则返回true;否则false
- 内部逻辑如下所示:
//a instanceof b
function _instanceof(a,b){
var aProto = a.__proto__;
var result = false;
do{
if(aProto === b.prototype){
result = true;
break;
}else{
aProto = aProto.__proto__;
}
}while(aProto)
return result;
}
11、继承有什么作用?
- 继承可以直接使用另一个对象的属性和方法
- 优化代码结构和对象关系
- 优化内存空间
12、下面两种写法有什么区别?
//方法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()作为构造函数的方法,在实例化的时候,每次都要创建printName(),作为新对象的私有属性
//方法2是将printName()作为构造函数原型上的方法,在实例化的时候,p1可以调用,其它的实例也可以来调用,是作为共享的方法,可以优化内存空间
13、 Object.create
有什么作用?兼容性如何?
- 作用:Object.create() 方法使用指定的原型对象和其属性创建了一个新的对象,如下代码
var a = {
name: 'a'
};
var b = Object.create(a);//b.__proto__ === a
-
兼容性如下图
兼容性
14、hasOwnProperty
有什么作用? 如何使用?
- 作用:hasOwnProperty() 检查该属性是否是其自有属性,而不是在原型链上找到的
- 使用如下:
var a = {
name: 'a'
};
a.hasOwnProperty('name');//true
a.hasOwnProperty('toString');//false
a.hasOwnProperty('valueOf');//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;
}
/*
调用Person这个函数,将它的this替换成Male实例化时产生的新对象,使该对象拥有name、sex
*/
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,age){
this.name = name;
this.age = age;
}
Person.prototype.getName = function(){
console.log('my name is ' + this.name);
};
function Male(name,age,sex){
Person.call(this,name,age);
this.sex = sex;
}
Male.prototype = Object.create(Person.prototype);
//手动更改Male.prototype的constructor
Male.prototype.constructor = Male;
// 在继承函数之后写自己的方法,否则会被覆盖
Male.prototype.getSex = function(){
console.log(this.sex);
}
var male = new Male('若愚',27,'男');
版权声明:本教程版权归邓攀和饥人谷所有,转载须说明来源!!!!
网友评论