apply、call 、bind有什么作用,什么区别
- 都可以用来改变函数的 this 指向
- 传入的第一个参数都是 this
- 都可以使用后续参数传参
- apply 的传入参数为数组。数组字面量(如:
fun.apply(this, ['eat', 'bananas'])
)或者数组对象(如:fun.apply(this, new Array('eat', 'bananas'))
) - call 的传入参数为参数列表(如:
fun.apply(this, 'eat', 'bananas')
) - apply、call 都会立即执行,bind 需要手动执行。如:
fun.bind(this, 'eat', 'bananas')()
bind() 函数会创建一个新函数(称为绑定函数),新函数与被调函数(绑定函数的目标函数)具有相同的函数体。当新函数被调用时 this 值绑定到 bind() 的第一个参数,该参数不能被重写。绑定函数被调用时,bind() 也接受预设的参数提供给原函数
MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
以下代码输出什么?
var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi() var john = {
firstName: "John"
}
function func() {
alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()
输出结果:John: hi!
下面代码输出什么,为什么
```js
func()
function func() {
alert(this)
}
```
输出结果
[object Window]
原因:this 指向 window
下面代码输出什么
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
输出结果
- document
- window
下面代码输出什么,why
var john = {
firstName: "John"
}
function func() {
alert( this.firstName )
}
func.call(john)
输出结果
John
- 原因:
call
的第一个参数为函数的this
的值
以下代码有什么问题,如何修改
var module= {
bind: function(){
$btn.on('click', function(){
console.log(this) //this指什么
this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
输出结果
console.log(this)
输出$btn
对应 DOM 元素
this.showMsg()
报错,提示this.showMsg
不是一个函数原因
DOM元素绑定事件时,此时的 this 指向对应的 DOM 元素,所以console.log(this)
输出$btn
对应 DOM 元素,而this.showMsg
上并没有showMsg()
这个函数,所以报错改进如下
var module = {
bind: function(){
var _this = this // 增加 this 指向标记
$('button').on('click', function(){
console.log(_this) //this指什么
_this.showMsg();
})
},
showMsg: function(){
console.log('饥人谷');
}
}
有如下代码,解释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.constructor
等于Person
-
p.__proto__
等于Person.prototype
-
Person.prototype.__proto__
等于Object.prototype
上例中,对对象 p可以这样调用 p.toString()
。toString
是哪里来的? 画出原型图?并解释什么是原型链。
原型链: 每个对象都有一个私有属性(称之为 [Prototype
]),它持有一个连接到另一个称为其 prototype 对象(原型对象)的链接。该 prototype 对象又具有一个自己的原型,层层向上直到一个对象的原型为 null
根据定义,null
没有原型,并作为这个原型链中的最后一个环节
参考:MDN
对String
做扩展,实现如下方式获取字符串中频率最高的字符
var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
String.prototype = {
getMostOften: function() {
var obj = {}
for (var i = 0; i < this.length; i++) {
var k = this[i]
console.log(k)
if(!obj[k]){ // 是否第一次出现,如果是 等于1
obj[k] = 1
} else {
obj[k] ++ // 相同的字母 +1
}
}
// console.log(obj)
var num = 0,letter;
for (var key in obj) {
if(obj[key] > num) {
num = obj[key]
letter = key
}
}
var result = '出现最多次数的字母是:' + letter + ', ' + num + '次'
return result
}
}
instanceOf
有什么作用?内部逻辑是如何实现的?
instanceof
运算符用来测试一个对象在其原型链中是否存在一个构造函数的prototype
属性通过 JS 代码展示
instanceOf
运算符的逻辑如下
function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
var O = R.prototype;// 取 R 的显示原型
L = L.__proto__;// 取 L 的隐式原型
while (true) {
if (L === null)
return false;
if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
继承有什么作用?
- 继承:创建一个或多个类的专门版本类方式称为继承(Javascript只支持单继承)。 创建的专门版本的类通常叫做子类,另外的类通常叫做父类。 在Javascript中,继承通过赋予子类一个父类的实例并专门化子类来实现。在现代浏览器中可以使用 Object.create 实现继承。通过继承可以减少代码冗余
参考:MDN
下面两种写法有什么区别?
//方法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 p2 = new Person('若愚', 27);
返回结果如图
通过 hasOwnProperty()
方法得到结果如图
第一种方法中的 printName
属性属于自身的直接的属性,第二种方法中的printName
属性属于原型链上的属性
Object.create
有什么作用?兼容性如何?
Object.create()
方法会使用指定的原型对象及其属性去创建一个新的对象
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
// 因为使用“.prototype =...”后, constructor 会改变为“=...”的那个 constructor,所以要重新指定.constructor 为自身。
hasOwnProperty
有什么作用? 如何使用?
hasOwnProperty()
方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性
例子
var People = function(a){
this.a = a
}
People.prototype = {
call: function(){
console.log(this.a)
}
}
var tom = new People("tom")
tom.hasOwnProperty("a")
true
tom.hasOwnProperty("call")
false
如下代码中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 方法时传递过来的对象,实现继承 Person 的方法
补全代码,实现继承
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("name: " + this.name)
};
function Male(name, sex, age){
Person.call(this, name, sex)
this.age = age
}
Male.prototype = Object.create(Person.prototype)
Male.prototype.constructor = Male
Male.prototype.getAge = function(){
console.log("age: " + this.age)
};
Male.prototype.printName = function(){
console.log("name: " + this.name)
};
var ruoyu = new Male('若愚', '男', 27);
ruoyu.printName();