高级2 this_原型链_继承

this 相关问题

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

call apply,调用一个函数,传入函数执行上下文及参数

    var value = 100
    var obj = {
      value: 200
    }
    function fn(a, b){
      console.log(this.value + a + b)
    }

    fn(3, 4) //107, 因为 fn 中的 this 指全局对象 window
    fn.call(obj, 3, 4) //207 指定fn中的执行上下文 obj,接着传入fn的参数 3, 4
    fn.apply(obj, [3, 4]) //207 apply和call基本一样,只是使用方法不一样,apply第二个参数为数组,用来传入fn中

bind,返回一个新函数,并且使函数内部的this为传入的第一个参数

    var obj1 =  {
      name: 'Neo',
      fn: function(){
        console.log(this) //{name: "Neo", fn: ƒ}
      }
    }
    var obj2 = {a: 2}
    var fn2 = obj1.fn.bind(obj2) //指定fn中 this 为 obj2
    fn2() // 输出obj2:{a: 2} 如果给fn2赋值的时候没有使用bind,则此时输出obj1:{name: "Neo", fn: ƒ},因为赋值时,是obj1对象在调用其方法 fn

2: 以下代码输出什么?

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

输出 John: hi!
首先把func赋值给了john对象的方法sayHi,然后john调用sayHi
对象调用方法时,方法中的this绑定到该对象

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

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

输出 window对象
在函数被直接调用时,this绑定到全局对象。在浏览器中,window就是该全局对象

4:下面代码输出什么

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

分别输出 document DOM对象 和 window对象
DOM对象绑定事件时,传入的函数中的this绑定到该DOM对象
setTImeout 和 setInterval 这两个方法执行的函数中的this绑定到全局对象window

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

var john = { 
  firstName: "John" 
}

function func() { 
  alert( this.firstName )
}
func.call(john)

输出 John
func调用call方法来执行时,call中传入john对象,意在绑定func中的this为john对象

6: 以下代码有什么问题,如何修改

var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) //this指 $btn
      this.showMsg();
    })
  },
  
  showMsg: function(){
    console.log('前端');
  }
}

在事件监听函数中 this.showMsg(), this指代 $btn 这个jQuery对象,并不代表module对象,因此 this.showMsg() 相当于 $btn.showMsg()
想要在事件监听函数中 调用module 的方法,可以人为把this绑定到module对象,使用 bind() 即可:

var module= {
  bind: function(){
    $btn.on('click', function(){
      console.log(this) //现在this指module对象
      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();

p是Person类创建的实例对象,p具有_ proto_属性,指向Person的prototype属性,prototype对象有constructor属性,指向了Person,prototype也有_ proto_属性,因为prototype也是个对象,是由Object类生成的实例。
同时Person也有_ proto_属性,指向了Function的prototype,Function 可以理解为函数之父,包括Person类 和 Object类都是Function创建的,同时Function创建了自己。

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

如图所示,p自身没有toString,就到Person类的prototype去找,也没有,prototype是个对象,由Object类创建,但是仍然没有toString,所以继续到prototype的_ proto _ 也就是Object的prototype中去找,最终找到了toString方法。


以上读取toString属性的搜索过程,是沿着由_ proto _ 组成的链子一直走的,这个链子,就叫做『原形链

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

var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次

方法如下:

<script>

String.prototype.getMostOften = function(){
  //声明空对象,和只有一个值的数组(数组是对象,便于后面存储其他属性)
  var obj = {}, temp = [0]
  //遍历调用其的this字符串,如果obj有当前属性,则 +1,没有则创建当前属性,并赋初值为 1
  for(var i = 0; i < this.length; i++){
    if(obj[this[i]]){
      obj[this[i]]++
    }else{
      obj[this[i]] = 1
    }
  }
  //得到对象后,格式如: {a: 2, b:3, c:1}
  //接着遍历对象,当前属性值如果大于temp数组存的值,则去覆盖temp数组,同时给temp数组(对象)添加key属性,用于存储字符名
  for(var key in obj){
    if(obj[key] > temp[0]){
      temp[0] = obj[key]
      temp.key = key
    }
  }
  //如此便能迭代出次数最高的字符
  return '出现最多次的是:' + temp.key + ',次数是:' + temp[0]
}

var str = 'ahbbccdeddddfg';
var ch = str.getMostOften();
console.log(ch); //d , 因为d 出现了5次

</script>   

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

instanceof操作符,我们常用来判断一个对象是不是某个类型的实例。
实际上,instanceof 运算符正是用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。

如果一个对象通过沿着 _ proto _ 组成的原形链一层层查找其constructor属性,如果找到了则,该对象是某类型的实例。

之前的例子中,p就是Person的实例,也是Object的实例,因为可以通过原形链最终找到constructor指向了Person或者Object。

继承相关问题

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('晓风', 23);

直观的区别是:

  • 方法1中, 把printName方法直接定义在了构造函数里;
  • 而方法2中,把printName方法写入到Person类的原型上。

间接的影响是:

  • 方法1每次构造新的对象,都会给对象绑定printName方法,存在浪费;
  • 方法2 中的p1对象继承了Person类原型上的printName方法,以后再构造新对象,也是引用自类的原型上的方法,节省了内存(虽然本例中感觉微乎其微),也便于后续维护,因为直接修改原型即可。

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

Object.create方法,可以创建一个拥有指定原型和属性的新对象
比如:

Student.prototype = Object.create(Person.prototype)

创建一个新对象,指定这个新对象的 _ _ proto_ _ 为Person.prototype,然后把这个对象赋值给prototype,为什么不能直接赋值?因为存在引用关系,修改了子类原型,其父类原型也会改变,所以需要clone一份,再去赋值。
Object.create是ES5中的方法,如果要兼容性更好一些,可以通过如下方法,手动创建空对象(只拥有_ _ proto_ _ ),并且这个空对象的构造函数的原型已经指向了Person.prototype,然后把这个对象赋值给Student.prototype

fn.prototype = Person.prototype
function fn(){}
Student.prototype = new fn()

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

hasOwnPerperty是Object.prototype的一个方法,用来判断一个对象是否包含自定义属性而不是原型链上的属性

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

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('晓风', 23)
p1.hasOwnProperty('name')  //true
p1.hasOwnProperty('printName')  //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;
}

call的作用是,指定Person执行上下文中的this 为当前Male创建的新对象。

在Male构造函数中执行Person构造函数,并且指定了this。
这样通过Male构造出的对象,便能继承拥有Person中的属性,也就是name 和sex。
出了使用call,还可以使用bind方法,也是指定this:

Person.bind(this)(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 xiaofeng = new Male('晓风', '男', 23);
xiaofeng.printName();

实现方法如下:

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 = Object.create(Person.prototype) //继承方法
Male.prototype.constructor = Male //修正constructor

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

var xiaofeng = new Male('晓风', '男', 23);
xiaofeng.printName();
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,761评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,953评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,998评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,248评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,130评论 4 356
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,145评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,550评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,236评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,510评论 1 291
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,601评论 2 310
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,376评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,247评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,613评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,911评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,191评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,532评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,739评论 2 335

推荐阅读更多精彩内容