美文网首页
Web36.this_原型链_继承

Web36.this_原型链_继承

作者: FiredEarthMusic | 来源:发表于2017-11-03 18:51 被阅读5次
console.log(this)
//window
var a = 1
//全局变量  相当于window的属性
window.a
//1
this.a
//1
var a = 1
var b = 100
console.log(this)  //window
function fn1(){
    console.log(a)
    console.log(this)  //window
    var b = 2
    console.log(this.b);  //100
}
fn1()
setTimeout setInterval
这两个方法执行的函数this也是全局对象
document.addEventListener('click', function(e){
    console.log(this);
    setTimeout(function(){
        console.log(this); //window
    }, 200)
}, false);
保存起来
//var _this = this;
//var me = this;
//var self = this;

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

作为构造函数调用

所谓构造函数 就是通过这个函数生成一个新对象(object)
这时 this就指这个新对象

new运算符接受一个函数F及其参数  new F(arguments...) 这一过程分三步

1.创建类的实例  这步是把一个空的对象的 __proto__属性设置为
   F.prototype
2.初始化实例  函数F被传入参数并调用 关键字this被设定为该实例
3.返回实例
function Person(name){
    this.name = name;
}
Person.prototype.printName = function(){
    console.log(this.name)
}

var p1 = new Person('Byron')
var p2 = new Person('Casper')
var p3 = new Person('Vincent')

p1.printName();
p2.printName();
p3.printName();
作为对象方法调用
在js中 函数也是对象  因此函数可以作为一个对象的属性 此时该函数被
称为该对象的方法 在使用这种调用方法时 this被自然绑定到该对象上

var obj1 = {
    name: 'Byron',
    fn: function(){
        console.log(this);
    }
}
obj1.fn()  //Object {name: 'Byron'}


var obj2 = {
    name: 'Byron',
    obj3: {
        fn: function(){
            console.log(this)
        }
    }
}
obj2.obj3.fn()  //Object   -----指向fn


var fn2 = obj1.fn
fn2()   //window
「读」属性时会沿着原型链搜索。

「新增」属性时不会去看原型链(但是如果你给这个属性加了一些配置,则不一样)。
比如求数组中最大值
var arr = [1,2,7,4]
//Max.max(1,2,7,4)
console.log( Math.max.apply(null, arr) )
再比如
function joinStr(){
    console.log( Array.prototype.join.call(arguments, '-') )
    
    //或者
    var join = Array.prototype.join.bind(arguments)
    console.log(join('-'))
}
joinStr('a', 'b', 'c')

三种变量

实例变量: (this)类的实例产能访问到的变量
静态变量: (属性)直接类型对象能访问到的变量
私有变量: (局部变量) 当前作用域类有效的变量

继承

继承指一个对象直接使用另一个对象的属性和方法

function Person(name, age){
  this.name = name
  this.age = age
}
Person.prototype.sayName = function(){
  console.log('My name is ' + this.name)
}
Person.prototype.walk = function(){
  console.log(this.name + 'is walking')
}

var p = new Person('ruoyu', 100)

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

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


Student.prototype.doing = function(){
  console.log('I am studing')
}

var s = new Student('hunger', 2, 'boy')
s

//Student.prototype.__proto__ = Person.prototype

function People(name){
  this.name = name;
  this.sayName = function(){
    console.log(this.name)
  } 
}

People.prototype
//Object {}
People.prototype.a = 1
//1
People.prototype
//Object {a: 1}
p = new People()

p.__proto__
//Object{}

this相关问题

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

Function.prototype.bind
bind  任何函数都有bind方法
bind  返回一个新函数,并且使得函数内部的this
为传入的第一个参数

var fn3 = obj1.fn.bind(obj1);
fn3

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

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

fn.call(context, param1, param2...)
fn.apply(context, paramArray)
call与apply功能完全一样,参数的用法不一样

var value = 100
var obj = {
    value: 200
}
function fn4(a, b){
    console.log(this.value + a + b)
}
fn4(3, 4)  //107
fn4.call(obj4, 3, 4)  //207
fn4.apply(obj4, [3, 4])  //207

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

2.png
//为 john对象新增一个属性sayHi
//结果为
//"John: hi!"

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

3.png
//结果为
//[object window]
//此时this指向window 所以打印出window对象

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

4.png
//结果为
#document
Window{...}

//第一个 为dom元素绑定事件 所以this指向#document
//而setTimeout指向window

题目5:下面代码输出什么

5.png
弹窗 John
//call 使this指向john对象

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

6.png
console.log(this)  //这个this指的是$btn
this.showMsg()  //不能运行 $btn中没有这个方法

//改进
var module = {
  bind: function(){
    var _this = this
    $btn.on('click', function(){
        console.log(this)
        _this.showMsg()
    })
  },
  showMsg: function(){
      console.log('checked');
  }
}

原型链相关问题

题目7:有如下代码 解释Person prototype proto p constructor之间的关联

7.png
Person.prototype.constructor === Person
Person.prototype === p.__proto__
p.__proto__.constructor === Person
Person.prototype.__proto__ === Object.prototype

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

p本身没有这个方法
p从原型中继承得到toString()方法

因为任何类的prototype属性本质上都是个类Object的实例,所以prototype也和其它实例一样也有个__proto__内部属性,指向其类型Object的prototype

我们大概可以知道为什么了,自己的类的prototype找不到的话,还会找prototype的类型的prototype属性,这样层层向上查找

大概过程是这样的

记当前对象为obj,查找obj属性、方法,找到后返回

没有找到,通过obj的__proto__属性,找到其类型Array的prototype属性(记为prop)继续查找,找到后返回

没有找到,把prop记为obj做递归重复步骤一,通过类似方法找到prop的类型Object的 prototype进行查找,找到返回

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

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

<script>
    String.prototype.getMostOften = function(){
        var _this = this
        var obj = {}
        for(var i=0; i<_this.length; i++){//循环这个字符串
            if(obj[_this[i]]){
                obj[_this[i]]++
            } else {
                obj[_this[i]] = 1
            }
        }
        var maxNum = 0,
            maxKey
        for (var key in obj) {
            if(obj[key] > maxNum) {
                maxNum = obj[key]
                maxKey = key
            }
        }
        return {
            maxKey,
            maxNum
        }
    }
    var str = 'ahbbccdeddddfg';
    var ch = str.getMostOften()
    console.log(ch)
</script>

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

instanceof用来检测一个对象在其原型链中是否存在一个构造函数的
prototype属性

object instanceof constructor

function _instanceof(obj,fn) {
  var nextobj = obj.__proto__
  do {
    if(nextobj === fn.prototype) {
      return true;
    } else {
    nextobj = nextobj.__proto__;
    }
  }while(nextobj)
    return false;
  }

继承相关问题

题目11:继承有什么作用?

减少重复,使得一个对象可以直接使用另一个对象的属性和方法

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

12.png
方法2将 方法放在原型链上,可以增加复用性

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

Object.create(proto[, propertiesObject])
Object.create() 方法会使用指定的原型对象及其属性去创建一个新的对象
兼容性.png

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

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

o = new Object();
o.prop = 'has';
o.hasOwnProperty('prop')                      //true
o.hasOwnProperty('toString')                 //false
o.hasOwnProperty('hasOwnProperty')  //false

题目15:如下代码中call的作用是什么?

15.png
使得Person函数在此作用域下能够被访问和继承

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

16.png
function Person(name, sex){
        this.name = name
        this.sex = sex
    }
    Person.prototype.getName = function(){
        console.log('My name is ' + this.name)
    }

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

    Male.prototype = Object.create(Person.prototype);

    Male.prototype.getAge = function(){
        console.log(this.age);
    }
    var ruoyu = new Male('若愚', '男', '28')
    ruoyu.getName();

相关文章

  • Web36.this_原型链_继承

    三种变量 实例变量: (this)类的实例产能访问到的变量静态变量: (属性)直接类型对象能访问到的变量私有变量:...

  • 继承

    原型链直接继承 原型链直接继承prototype 原型链继承_prototype属性 继承_构造函数绑定

  • js中的实现继承的几种方式

    大纲:原型链借用构造函数组合继承原型式继承寄生式继承寄生组合式继承 1、原型链: 什么是原型链? 原型链的基本思想...

  • JavaScript 原型、原型链与原型继承

    原型,原型链与原型继承 用自己的方式理解原型,原型链和原型继承 javascript——原型与原型链 JavaSc...

  • js基础之实现继承的几种方式

    js 实现继承的方式有: 原型链继承; 构造函数继承; 组合继承(原型链继承 + 构造函数继承)(最常用);(原型...

  • es5的部分继承以及es6的class

    一、JavaScript常用的原型继承方式 原型链继承 2,构造函数继承(对象冒充继承) 3,组合继承(原型链继承...

  • 构造函数原型的继承方式分析

    1.通过原型链继承 综上我们可以总结出 通过原型链来实现继承的原理通过原型链来实现继承的原理原型链继承方案中,父类...

  • Javascript 面向对象的程序设计(原型链与继承)

    继承 原型链 讲原型的时候提到过继承,设计原型的初衷就是为了继承,原型链是实现继承的主要方法。那什么是原型链,还记...

  • JavaScript继承方式详解

    JavaScript实现继承的方式主要有两种: 原型链继承和借助构造函数继承 一、原型链继承 原型链继承的主要思想...

  • js_继承及原型链等(四)

    js_继承及原型链等(三) 1. 继承 依赖于原型链来完成的继承 发生在对象与对象之间 原型链,如下: ==原型链...

网友评论

      本文标题:Web36.this_原型链_继承

      本文链接:https://www.haomeiwen.com/subject/fytapxtx.html