this_原型链_继承

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();

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Linyb极客之路

浅谈Java中的hashcode方法

哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率。在Java的Object类中有一个方法:

411
来自专栏云霄雨霁

Java--自动装箱、拆箱与遍历循环

17210
来自专栏精讲JAVA

Java知识点总结之Java泛型

772
来自专栏林冠宏的技术文章

由 System.arraycopy 引发的巩固:对象引用 与 对象 的区别

首先明确一点,System.arraycopy 操作的是数组,效果是深复制。 是不是觉得怎么和你印象的中不一样? 重点来了,对于对象数组,例如: User[]...

994
来自专栏每日一篇技术文章

Swift3.0 - 对象和类

1.对象中的所有变量或者常量在定义时如果不初始化,在对象初始化的时候,必须初始化,这个是swift安全性考虑,可选类型没有强制性要求初始化,因为系统默认给可选类...

671
来自专栏微服务生态

Scala学习笔记(一)

lazy val forLater = someTimeConsumingOperation()

541
来自专栏coding for love

JS原生引用类型解析1-Object类型

(注1:如果有问题欢迎留言探讨,一起学习!转载请注明出处,喜欢可以点个赞哦!) (注2:更多内容请查看我的目录。)

371
来自专栏陈树义

《JavaScript程序设计》第2课:JS类型系统

JS类型系统可以分为标准类型和对象类型,进一步标准类型又可以分为原始类型和引用类型,而对象类型又可以分为内置对象类型、普通对象类型、自定义对象类型。 ? 1. ...

3087
来自专栏积累沉淀

Python快速学习第六天

第六天: 面向对象 1. 面向对象的特点——多态,封装,继承  对象:包括特性和方法,特性只是作为对象的一部分变量,而方法则是存储在对象内的函数。 (1)多态—...

1817
来自专栏HTML5学堂

JavaScript 运行机制之执行顺序详解

1、代码块 定义:JavaScript中的代码块是指由<script>标签分割的代码段。 示例: <script> 代码块一 </script> <scr...

26011

扫码关注云+社区