31.this,原型链,继承

一. this

参考
1.深入浅出妙用 Javascript 中 apply、call、bind
2.理解 JavaScript 中的 Function.prototype.bind
3.this 关键字

1. apply、call 、bind有什么作用,什么区别
  • 作用:三者都可以固定this的值,避免出现意想不到的情况
    • fun.call(thisArg[, arg1[, arg2[, ...]]])
      call() 方法调用一个函数, 其具有一个指定的this值和分别地提供的参数(参数的列表)
    • fun.apply(thisArg, [argsArray])
      apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组或类数组对象作为函数执行时的参数
    • fun.bind(thisArg[, arg1[, arg2[, ...]]])
      创建了一个函数,当这个函数在被调用的时候,它的 this 会被设置成被传入第一个值。
  • 区别:

1.apply/callbind
bind改变了this值后没有立即执行,而apply和call都是立即执行的

var obj = {
  a:1
}

var foo = {
  getA: function(){
    console.log(this.a)
  }
}

foo.getA()  //undefined
foo.getA.bind(obj)()  //1
foo.getA.call(obj)  //1
foo.getA.apply(obj)  //1

2.applycall
apply的第二个参数是数组或类数组对象,call接受的则是若干个参数

var arr = [1,2,3,4,9]
console.log(Math.max.apply(Math,arr))  //9
console.log(Math.max.call(Math,1,2,3,4,9))//9
2.以下代码输出?
var john = { 
  firstName: "John" 
}
function func() { 
  alert(this.firstName + ": hi!")
}
john.sayHi = func  //john对象添加sayHi方法,方法为func
john.sayHi()  //"John: hi!"   执行,此时this为john
3.以下代码输出?
func()  //[object Window] 全局作用域下函数,this绑定为全局对象
function func() { 
  alert(this)
}

4.以下代码输出?
document.addEventListener('click', function(e){
    console.log(this);   //document 在事件处理程序中this代表事件源对象
    setTimeout(function(){
        console.log(this); //window setTimeout函数始终是在全局作用域下调用的,所以this在非严格模式下指向window
    }, 200);
}, false);

5.以下代码输出?
var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName )
}
func.call(john)  
//John  call方法将func的this指定为john对象,所以this.firstName就是"John"了
6.以下代码有什么问题,如何修改
var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) //this指什么$btn而并非module,不能调用module下的showMsg方法
      this.showMsg();
    })
  },
  
  showMsg: function(){
    console.log('没什么');
  }
}

//修改
var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this)
      this.showMsg();
    }.bind(this))
  },
  
  showMsg: function(){
    console.log('没什么');
  }
}

二.原型链
1.有如下代码,解释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("haha")
p.sayName();
//1.定义Person构造函数,Person构造函数自带prototype属性
//2.prototype属性中有constructor属性,指向构造函数
//3.每个构造函数的实例都有__proto__属性,指向构造函数的prototype属性
2.上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。
31.this,原型链,继承_第1张图片
Person不完全原型图

如图示,Person构造函数中没有toString()方法,所以继续在其原型中查找,也没有,所以Person.prototype的原型,即Object.prototype中查找,然后找到了对象原型中的toString()方法

对象的属性和方法,有可能是定义在自身,也有可能是定义在它的原型对象。由于原型本身也是对象,又有自己的原型,所以形成了一条原型链(prototype chain)原文链接

3.对String做扩展,实现如下方式获取字符串中频率最高的字符
String.prototype.getMostOften = function(){
  var i, obj = {}
  var textSplit = this.split('')
  for(i= 0; i index){
      max = key
      index = obj[key]
    }
  }
  return max
}

var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
4.instanceof有什么作用?内部逻辑是如何实现的?
  • instanceof判断对象是否为某个构造函数的实例;
  • 内部逻辑:判断构造函数的原型是否在对象的原型链上,在就返回true,反之false
//例
function Person(name){
    this.name = name;
}
Person.prototype.sayName = function(){
    console.log('My name is :' + this.name);
}
var p = new Person("haha")

console.log(p instanceof Person)  //true
console.log(p instanceof Object)  //true
三.继承
1.继承有什么作用?

继承是指一个对象可以直接使用另一个对象的属性和方法,继承提高了代码复用性,减少重复劳动

2.下面两种写法有什么区别?

方法1的实例之间属性和方法都是独立的,共用的属性和方法不能共享,同时也浪费资源
方法2的实例之间printName方法是共享的

//方法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);

3.Object.create 有什么作用?兼容性如何?

Object.create(proto, [ propertiesObject ]):创建一个对象,使其原型为传入的第一个参数
兼容性:IE 9+

4.hasOwnProperty有什么作用? 如何使用?

hasOwnPerpertyObject.prototype的一个方法,可以判断一个对象是否包含自定义属性而不是原型链上的属性,hasOwnProperty是JavaScript中唯一一个处理属性但是不查找原型链的函数

function Person(name, sex){
    this.name = name
    this.sex = sex
    this.printSex = function(){
      console.log(this.sex)
    }
}

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('小明', 27);
console.log(p1.hasOwnProperty('printSex'))  //true
console.log(p1.hasOwnProperty('printName'))  //false
5.如下代码中call的作用是什么?
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}
function Male(name, sex, age){
    Person.call(this, name, sex);    //这里的call 用于继承Person的属性
    this.age = age;
}
//在实例化后male里面就可以获取到name,sex属性
var male1 = new Male('xiaoming','男',12)
console.log(male1.name,male1.sex,male1.age) //xiaoming 男 12

6.补全代码,实现继承
function Person(name, sex){
    this.name = name
    this.sex = sex
}

Person.prototype.getName = function(){
    console.log(this.name)
};    

function Male(name, sex, age){
   Person.bind(this)(name,sex)
   this.age = age
}

var _prototype = Object.create(Person.prototype)
_prototype.constructor = Male
Male.prototype = _prototype

Male.prototype.getAge = function(){
    console.log(this.age)
};

var ruoyu = new Male('ruoyu', '男', 27);
ruoyu.getName();//ruoyu

你可能感兴趣的:(31.this,原型链,继承)