this 相关问题
1:构造函数调用: new S() ==>指向创建对象本身{a:'a'}
2:方法调用:method,property
var p={
s:function(){
console.log(this)
}
}
p.s()==>this指向调用方
3:apply,call的调用
p.s.call({a:1},1,2)
p.s.apply({a:1},[1,2]) //手动指定this
4: 函数调用
var cache=p.s;
cache()==>this指向全局
p.s()==>this指向p
问题1: apply、call 、bind有什么作用,什么区别
apply:在调用一个存在的函数时,你可以为其指定一个 this对象。 this指当前对象,也就是正在调用这个函数的对象。 使用 apply, 你可以只写一次这个方法然后在另一个对象中继承它,而不用在新对象中重复写该方法。
fun.apply(thisArg, [argsArray])
var arr=[1,2,3,6,0,3]
Math.max.apply(null,arr)//6
//传入null,undefined为相当于全局作用域this=window
thisArg
在 fun 函数运行时指定的 this值。需要注意的是,指定的 this值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
argsArray一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null或 undefine,则表示不需要传入任何参数
apply 与 call()非常相似,不同之处在于提供参数的方式。apply 使用参数数组而不是一组参数列表(原文:a named set of parameters)。apply
可以使用数组字面量(array literal),如 fun.apply(this, ['eat', 'bananas'])
,或数组对象, 如 fun.apply(this, new Array('eat', 'bananas'))
。
call:
fun.call(thisArg[, arg1[, arg2[, ...]]])
var arr=[1,2,3,6,0,3]
Math.max.call(this,arr[0],arr[2])//3
后面传入的参数必须为数组value的形式,不能是一个数组,其他的与apply相似
bind():bind()方法创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。
/*
语法:fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg当绑定函数被调用时,该参数会作为原函数运行时的 this 指向。当使用new操作符调用绑定函数时,该参数无效。arg1, arg2, ...当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。
*/
function Person(name, age) {
this.name = name;
this.age = age;
}
var _Person = Person.bind(null, 'hanzichi');
var p = new _Person(30); // Person {name: "hanzichi", age: 30}
问题2: 以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()//john:hi!
john.sayHi()=function(){
alert(this.firstName + ": hi!")
}
john调用了sayHi()方法,所以该方法内部this是john
问题3: 下面代码输出什么,为什么
func()
function func() {
alert(this)
}
弹出:object window//
函数声明前置,func()相当于是window.fun(),window调用,
等价于call 方法的func.call(undefined,null)
第一个参数为undefined或者null,作用域为window
问题4:下面代码输出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
//输出#document window
/*
首先:settimeout的执行肯定是在函数执行完再执行的
第二:document调用addEventListener方法所以this是document,
第三: setTimeout()相当于是setTimeout.call(null,function,delay),所以this时是window.,document的onclick
如果想输出的this的document可以用bind()方法改写*/
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}.bind(this), 200);
}, false);
问题5:下面代码输出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
fun.call(thisArg[, arg1[, arg2[, ...]]])
参数
thisArg在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于[非严格模式下]则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。arg1, arg2, ...指定的参数列表。
func.call传入的第一个参数为jhon,jhon为引用类型,所以func(obj)this值的是传入的参数,this.firstName='John'
问题6: 以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
上图中是btn调用on()方法,所以this指的是$btn节点,下面的 this.showMsg();,因为$btn没有定义过该方法,所以会报错
如果想要调用this.showMsg()
//方法1:
var module= {
bind: function(){
var _this=this
$btn.on('click', function(){
console.log(this) //this指什么
_this.showMsg()
})
},
showMsg: function(){
console.log('饥人谷');
}
}
//方法2:
var $btn=$('.btn')
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg()
}.bind(this))//on方法外面绑定this,指定this值为该对象
},
showMsg: function(){
console.log('饥人谷');
}
}
module.bind()
原型链相关问题
问题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();
![](https://img.haomeiwen.com/i6036420/9a9eef8db8015db7.jpg)
问题8: 上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
p中没有定义过toString()方法,所以会通过p.proto向上寻找,p.proto指向Person.prototype,Person.prototype中也没有定义过toString(),所以会向上寻找Person.prototype.proto找到Object,object有一个tosting的方法,如果object没有定义的,则会找不到,报错
![](https://img.haomeiwen.com/i6036420/3c51fdb194974034.jpg)
原型是什么prototype,通过原型这种机制,JavaScript 中的对象从其他对象继承功能特性
问题9:对String做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
String.prototype.getMostOften=function(str){
var arr=[];
for(var i=0;i<str.length;i++){
if(arr[str[i]]){
arr[str[i]]++
}else{
arr[str[i]]=1
}
}
var arr2=[]
for(var i in arr){
arr2.push(arr[i])
}
var max=Math.max.apply(null,arr2)
return max
}
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
问题10: instanceOf有什么作用?内部逻辑是如何实现的?
instanceof 运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。
var a=[]
a instanceof Array//true;
a instanceof Object//true;
Array._proto_指向了Object
所以两个都是返回都是true
继承相关问题
问题11:继承有什么作用?
一个对象不用声明就能拥有另一个对象的属性和方法为继承,在javascript中通过原型链来实现继承,JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依此层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
问题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);
p2.printName
function (){
console.log(this.name);
}
p1.printName
function (){
console.log(this.name);
}
p2.printName===p1.printName//false
//p1,p2通过new Person()的方式创建一个对象,然后返回的一个对象,返回的两个函数实际上声明两次,所以这两个方法内容一样,但是相等
var p4= new Person('火锅', 25);
p4.printName===p3.printName//true
通过原型方式声明的方法,因为本身并没有声明这个方法,而是通过object._proto_向上寻找,p3._proto_和p4._proto_对应原型的prototype对象其实是一个,所以他们相等,而且只需要声明一次。
问题13: Object.create 有什么作用?兼容性如何?
object.create() 方法使用指定的原型对象和其属性创建了一个新的对象。
语法
Object.create(proto, [ propertiesObject ])
参数
proto
一个对象,应该是新创建的对象的原型。
propertiesObject
可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()的第二个参数一样)。注意:该参数对象不能是 undefined
,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。
例如:
Object.create({a:1})//创建一个新的对象,该对象的_proto_属性指向传入的参数,即是新创建对象的原型,所以*第一个参数必须是对象
不支持ie8及以下版本
问题14: hasOwnProperty有什么作用? 如何使用?
hasOwnProperty() 方法会返回一个布尔值,指示对象是否具有指定的属性作为自身(不继承)属性。
function A(name){}
function A(name){this.name=name}
A.prototype={age:10,sex:'man'}
Object {age: 10, sex: "man"}
var a=new A('狗娃')
a.hasOwnProperty('name')//true
a.hasOwnProperty('age')//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;
}
function Person(name, sex){
this.name = name;
this.sex = sex;
}
function Male(name, sex, age){
Person.call(this, name, sex); //这里的 call 有什么作用
this.age = age;
}
var hhh=new Male('二狗子','男','25')
调用Person函数,以call的方式,第一个传入的参数this此时指的是Male内,当用new关键字的时候,this 指的就是hhh了
问题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){
this.name=name;this.sex=sex
}
Person.prototype.getName = function(){
console.log(this.name)
};
function Male(name, sex, age){this.age=age;
Person.call(this,name,sex);this.printName=function(){console.log(this.name)}
}
//todo ...
Male.prototype.getAge = function(){
console.log(this.age)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();
问题:
- 问题6方法三的代码调用call的行为是多余的。
- 问题8中toString不是来自Object,而是来自Object.prototype。
- 原型链解释错误。
- 问题9代码错误,不符合题意。
- 问题10老毛病,Array.proto指向了Object解释错误。
6.第十二题 // p1,p2通过new Person()的方式创建一个对象,然后返回的一个对象,返回的两个函数实际上声明两次,所以这两个方法内容一样,但是相等。 相等??确定?
网友评论