美文网首页
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_原型链_继承

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