Skip to content

this_原型链_继承 #66

@yongheng2016

Description

@yongheng2016

this 相关问题

问题1: apply、call 、bind有什么作用,什么区别

  • 作用:

    • apply 、 call 、bind 三者都是用来改变函数的this对象的指向的;
    • apply 、 call 、bind 三者第一个参数都是this要指向的对象,也就是想指定的上下文;
    • apply 、 call 、bind 三者都可以利用后续参数传参;
  • 区别:

    • bind 是返回对应函数,便于稍后调用,只能绑定一次(多次绑定无效)
var obj = {name: '老王'}
function foo(){
   console.log(this.name)
}
var fun = foo.bind(obj)  //返回绑定指定this的函数
fun()
  • apply 、call 则是立即调用 。

参考:http://www.cnblogs.com/coco1s/p/4833199.html

问题2: 以下代码输出什么?

var john = { 
  firstName: "John" 
}
function func() { 
  alert(this.firstName + ": hi!")
}
john.sayHi = func
john.sayHi()   //输出:John:hi!

问题3: 下面代码输出什么,为什么

func() 
function func() { 
  alert(this)
}

输出: [object window]
func( )等价于func.call(undefined) -->this==undefined
在非严格模式下,undefined指向window

问题4:下面代码输出什么

document.addEventListener('click', function(e){
    console.log(this);
    setTimeout(function(){
        console.log(this);
    }, 200);
}, false);

输出:document window

问题5:下面代码输出什么,why

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指什么
      this.showMsg();  
    })
  },
  
  showMsg: function(){
    console.log('饥人谷');
  }
}
  • this.showMsg()中的this指向的是事件绑定的Dom元素,所以取不到值
  • 修改1:
var module = {
   bind:function(){
      _this = this
      $btn.on('click', function (){
         console.log(_this)  
         _this.showMsg()
       })
   },

   showMsg: function (){
      console.log('饥人谷')
   }
}
  • 修改2:
var module = {
   bind:function(){
      $btn.on('click', function (){
         console.log(this)  
         this.showMsg()
       }.bind(this))
   },

   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();
  • Person: 是产生p实例的构造函数,通过Person(name)定义了p对象的name属性和继承方法
  • prototype: 每个构造函数都有一个prototype属性,每个生成的实例都是通过此属性来继承原型的一些方法和属性
  • __proto__: 每个实例对象都有此属性,通过此属性可以继承原型的方法和属性,是原型继承的渠道
  • p:由Person()构造函数创建的一个实例对
  • constructor: 构造函数的prototype下都有此属性,指向此构造函数

问题8: 上例中,对对象 p可以这样调用 p.toString()。toString是哪里来的? 画出原型图?并解释什么是原型链。

image

  • 原型链:

    • 任一对象调用某些属性或方法时,都会先从自身查找
    • 当自身不存在时,会通过_proto__查找原型是否存在
    • 若原型也不存在,则继续向上查找原型,类似这样依次查找
    • 类似这种关系所形成的联系,形成了原型链
  • javascript原型链图:

image

问题9:对String做扩展,实现如下方式获取字符串中频率最高的字符

var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次
String.prototype.getMostOften = function (){
   var objStr = {},
         max=0,
         maxKey
   for (var i=0; i<this.length; i++){
      if(objStr[this[i]]){
         objStr[this[i]]++
      }else{
         objStr[this[i]]=1
      }
   }
   
   for(var key in objStr){
      if (objStr[key]>max){
          maxKey = key
          max = objStr[key]
      }
   }

   return maxKey
}

问题10: instanceOf有什么作用?内部逻辑是如何实现的?

instanceOf作用:

  • 判断一个实例是否属于某种类型
function Foo(){ }
var foo = new Foo()
console.log(foo instanceOf Foo)   //true
  • 在继承关系中判断一个实例是否属于它的父类型
function Foo(){ }
function Aoo(){ }
Foo.prototype = new Aoo()
var foo = new Foo()
console.log(foo instanceOf Foo)   //true
console.log(foo instanceOf Aoo)   //true

instanciOf内部实现逻辑

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;
  }
}

参考:https://www.ibm.com/developerworks/cn/web/1306_jiangjj_jsinstanceof/index.html

继承相关问题

问题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方法
方法2:实例没有printName方法,但可以通过原型继承此方法
区别:方法2相对于方法1节省大量空间,但用到printName方法的时候通过原型查找使用,功能性没有损失

问题13: Object.create 有什么作用?兼容性如何?

  • Object.create: 创建一个新对象,此对象的原型为方法的第一个参数
Object.create(proto [, propertiesObject])   //第一个参数为要继承的原型,第二个参数设置新对象的属性
  • 第一个参数:要继承的原型
  • 第二个参数:
    • configurable:表示新创建的对象是否可配置,即:新对象的属性或方法是否可删除或修改,默认:false
    • enumerable:对象属性是否可枚举(for of),默认false
    • writable:是否能在新对象上添加新属性,默认false
    • get:对象getter函数,默认undefined
    • set:对象setter函数,默认undefined

使用Object.create()方法创建新对象时,如果不是继承一个原有的对象,而是要创建一个全新的对象,就要把proto参数设置为null。如果proto参数不是null或一个对象时,会抛出一个TypeError异常。

参考:https://itbilu.com/javascript/js/EkCyw5lHl.html

  • 兼容情况:
Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari
Basic support 5 4.0 (2) 9 11.60 5

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/create

问题14: hasOwnProperty有什么作用? 如何使用?

  • hasOwnProperty:返回一个布尔值,指示某个属性是否是自身属性(非继承属性)
obj.hasOwnProperty(prop)   //返回布尔值

所有继承了Object的对象都会继承hasOwnProperty( )方法,此方法可以用来检测某个属性是否为对象的自身属性,和in方法不同,此方法会忽略从原型上继承来的属性

  • 用法举例:
var obj = new Object()
obj.pro = 'hello'
obj.hasOwnProperty('pro')  //true
obj.hasOwnProperty('toString')  //false
obj.hasOwnProperty('hasOwnPropterty')  //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.call(this, name, sex):参数this指定了函数运行上下文,当Male创造实例时,实例对象即为this对象,因此也具有了Person內的属性;
  • 例:
var male = new Male('老王', '男', 33)
male = {
   name: '老王',
   sex: '男',
   age: 33
}

问题16: 补全代码,实现继承

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

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

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

Male.prototype = new Person()
Male.prototype.constructor = Male

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

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

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions