编程ES6Web前端之路

this_原型链_继承

2017-05-23  本文已影响49人  徐国军_plus

this 相关问题

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

在JS中,这三者都是用来改变函数的this对象的指向,相似点:

1.都是用来改变函数的this对象的指向的。
2.第一个参数都是this要指向的对象。
3.都可以利用后续参数传参。

不同之处:bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。
举个例子:

var obj = {
    x: 81,
};
 
var foo = {
    getX: function() {
        return this.x;
    }
}
 
console.log(foo.getX.bind(obj)());  //81
console.log(foo.getX.call(obj));    //81
console.log(foo.getX.apply(obj));   //81

三个输出的都是81,但是注意看使用 bind() 方法的,他后面多了对括号。
也就是说,区别是,当你希望改变上下文环境之后并非立即执行,而是回调执行的时候,使用 bind() 方法。而 apply/call 则会立即执行函数。

对于 apply、call 二者而言,作用完全一样,只是接受参数的方式不太一样。例如,有一个函数定义如下:

var func = function(arg1, arg2) {
 
};

就可以通过如下方式来调用:

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2])

其中 this 是你想指定的上下文,他可以是任何一个 JavaScript 对象(JavaScript 中一切皆对象),call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
JavaScript 中,某个函数的参数数量是不固定的,因此要说适用条件的话,当你的参数是明确知道数量时用 call 。
而不确定的时候用 apply,然后把参数 push 进数组传递进去。当参数数量不确定时,函数内部也可以通过 arguments 这个数组来遍历所有的参数。

2: 以下代码输出什么?

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

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

func() //弹出window对象,因为在全局作用域下调用,this指向全局对象
function func() { 
  alert(this)
}

4:下面代码输出什么

document.addEventListener('click', function(e){
//绑定事件中的this指向触发事件的元素对象,这里指的是document对象
    console.log(this);
    setTimeout(function(){
//setTimeout中的this指向全局对象window,所以输出window对象
        console.log(this);
    }, 200);
}, false);

上面代码输出document元素对象和window对象

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

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指向触发事件的元素对象,这里是$btn对象
      this.showMsg();   //$btn元素没有showMsg方法
    })
  },
  
  showMsg: function(){
    console.log('徐国军');
  }
}

修改:
var module= {
  bind: function(){
    var _this = this;   //保存this,this指向当前对象
    $btn.on('click', function(){
      console.log(this)
      _this.showMsg();   
    })
  },
  
  showMsg: function(){
    console.log('xuguojun');
  }
}

原型链相关问题

7:有如下代码,解释Person、 prototype、proto、p、constructor之间的关联。

function Person(name){
    this.name = name;
}
Person.prototype.sayName = function(){
    console.log('My name is :' + this.name);
}
------------------------------------------------------------------------------------------
Person.prototype = p._proto_,Person.prototype.constructor = Person
var p = new Person("徐国军")
p.sayName();//输出My name is :徐国军

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

Paste_Image.png

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

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

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

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

instanceof运算符用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。即判断是不是一个对象的实例,是返回 true,不是返回false。

var arr = [1,2,3],
    obj = {name:'xuguojun'};

arr instanceof Array     //true
    //内部逻辑为看实例的 __proto__ 是否等于构造函数的 prototype 。    
arr.__proto__ === Array.prototype //true
    //如果为 true ,则返回结果 true

arr instanceof Object     //true
    //内部逻辑为看实例的 __proto__ 是否为构造函数的 prototype 原型   
arr.__proto__ === Object.prototype //false
    //如果为 false ,则继续看下一层的 __proto__
arr.__proto__.__proto__ === Object.prototype //true
    //如果为 true ,则返回结果 true

obj instanceof Array     //false
    //内部逻辑为看实例的 __proto__ 是否为构造函数的 prototype 原型
obj.__proto__ === Array.prototype //false
    //如果为 false ,则继续看下一层的 __proto__
obj.__proto__.__proto__ === Array.prototype //false
    //如果到最深一层的 __proto__ (最深一层为null)比较还是不相等,则返回 false

11:继承有什么作用?

继承就是子类拥有父类的属性和方法。

作用:继承划分了类的层次性,父类代表的是更一般、更泛化的类,而子类则是更为具体、更为细化;继承是实现代码重用、扩展软件功能的重要手段。子类中与父类完全相同的属性和方法不必重写,因为通过继承,子类会拥有父类的属性和方法,不需要重新去写这些重复的代码,提高了代码的重用性。而只需写出新增或改写的内容,直接给子类添加新的属性和方法,子类就会拥有这些属性和方法,表现出多态化,而父类不会被“污染”,提高了代码的独立性。这就是说子类可以复用父类的内容,不必一切从零开始。

12: 下面两种写法有什么区别?

//方法1
function People(name, sex){
    this.name = name;
    this.sex = sex;
    this.printName = function(){
        console.log(this.name);
    }
}
var p1 = new People('xuguojun', 2)
//这种形式创建的p1本身有name、sex属性和printName方法

//方法2
function Person(name, sex){
    this.name = name;
    this.sex = sex;
}

Person.prototype.printName = function(){
    console.log(this.name);
}
var p1 = new Person('xuguojun', 25);
//这种形式创建的p1本身有name、sex属性,但没有printName方法,但p1能够通过原型链调用Person原型的printName方法。

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

作用:Object.create() 方法使用指定的原型对象和其属性创建了一个新的对象。

语法:Object.create(proto, [ propertiesObject ])

参数

proto

一个对象,应该是新创建的对象的原型。

propertiesObject

可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()
的第二个参数一样)。注意:该参数对象不能是 undefined
,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。

浏览器兼容性

Paste_Image.png
var me = {
    name: "cg",
    sayName: function(){
        console.log("My name is " + this.name);
    }
}
var p = Object.create(me)
    //以 me 对象为原型,创建了实例 p
p.__proto__ === me //true
image.png

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

hasOwnProperty() 方法会返回一个布尔值,判断一个属性是否是自身的属性,返回 true 或 false

示例:

function  People(name){
    this.name = name
}

People.prototype.sayName = function(){
    console.log("My name is " + this.name);
}

var p = new People("hi")

p.hasOwnProperty("name")  //true
    //name 是 p 自己的属性,所以返回true
p.hasOwnProperty("sayName")  //false
    //sayName 是 p 的原型 __proto__ 里的属性,不是自己的属性,所以返回false
image.png

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;
}
//作用:在Male函数中,调用Person函数,指定Person方法中的this为Male,使Male函数能够执行Person上的初始化代码,实现构造函数继承。

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){
    // todo ...
    this.name = name;
    this.sex = sex;
}

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

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

//todo ...
Male.prototype = Object.create(Person.prototype);
Male.prototype.constructor = Male;

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

var ruoyu = new Male('xuguojun', '男', 25);
ruoyu.getName();
上一篇下一篇

猜你喜欢

热点阅读