最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • js中的面向对象(一)

    正文概述 掘金(牛牛_lz)   2021-02-07   566

    面向对象要解决的问题

    提到面向对象,大家的第一反应就是封装、继承和多态。对其做如下解释:

    • 封装:影藏细节(A对A——将多行代码取个名字或A对B——API调用合作)
    • 继承:继承的意思就是同上跟上述一样,直接用另外一件事情的属性和方法,只需要写自己需要的属性和方法即可。
    • 多态:一个东西拥有两种或者多种东西的属性

    因此,封装使我们减少沟通成本,也减少思维负担;继承可以让我们复用代码;而多态可以使一个东西更加灵活。

    封装、继承、多态并不是面向对象终极需求,而是写代码的套路问题(定势思维)

    封装和继承

    JS中跟类对应的叫做构造函数

    JS的七种数据类型:Number,String,bool,undefined,null,symbol(存的是值),object(复杂类型、引用类型、对象,存的是内存地址)。

    而Object包括如下三种情形:

    1. 普通对象
    2. 数组
    3. 函数(重中之重)

    原型链(对象与对象)

    var obj = {name:"Jack", age:18}
    

    如上定义一个obj,我们可以访问name和age,但是我们可以访问obj.toString(),那么toString方法来自哪里?在控制台使用console.dir()可以看到toString方法来自__proto__。

    js中的面向对象(一)

    但是,在编程中,不要使用obj.__proto__来访问,这样访问会造成很多性能上的降低。

    var obj = {name: 'Jack', age: 20}
    var obj2 = {name: 'John', age:22}
    obj.__proto__.gender = '男'
    console.log(obj2.gender)    // 会打印出‘男’
    // 用户在访问obj2的时候,没有发现gender属性,故会去__proto__中寻找,
    // 由于在obj的__proto__中定义了gender为“男”,而且所有Object的__proto__都是共用的
    // 所以在访问obj2.gender的时候会得到“男”
    

    问:若没有声明一个对象,则怎么访问__proto__呢?

    答:window中有一个Object,使用window.Object可以得到,规定在window.Object中必须有一个protoType去存声明对象的__proto__的内存地址,因此可以通过window.Object.protoType得到跟声明对象中一致的__proto__

    window.Object.protoType.addr = "北京市丰台区"
    var obj = {}
    obj.addr    // 为“北京市丰台区” 
    

    问:原型链只能有一个吗?怎么实现Array中有push,而Object中没有push呢?

    答:Array的__proto__和Object的__proto__不一样。Array的__proto__中有push、pop等方法,而Array的__proto__的__proto__中有toString、valueOf等方法。如下图所示:

    js中的面向对象(一)

    Array中的__proto__ 因此obj.proto.__proto__被称作原型链。大写的Object是天生就有的,本身就有prototype属性的,而小写的object是声明的Object,必须声明之后才会有__proto__属性。

    js中的面向对象(一)
    var obj = {种族:'人类', 行走方式:'直立行走'}
    var person = {name:'Jack', age:18}
    var person2 = {name:'John', age:20}
    person.__proto__ = obj
    person.种族    // 人类
    person2.种族    // undefined
    person2.__proto__ = obj
    person2.种族    // 人类
    

    JS没有类,只需要给每一个加一个__proto__属性就可以实现继承。

    this(对象与函数)

    为什么说函数就是对象呢? 函数的本质是字符串再加上一些其他的东西。

    var obj = {
        name: 'f',
        length: 2,
        params: ['x', 'y'],
        functionBody: 'console.log("hello world")'
    }
    objGong = {
        call: function(x){
            eval(x.functionBody)
        }
    }
    obj.__proto__ = objGong
    obj.call(obj)   // 控制台会打印出“Hello world”
    
    var obj = {
        name: 'Jack',
        sayName: function(name){
            console.log('I am ' + name)
        }
    }
    
    // 在此调用的时候使用的方式是:obj.sayName(obj.name)
    
    // 可以改造成如下:
    var obj = {
        name: 'Jack',
        sayName: function(x){
            console.log('I am ' + x.name)
        }
    }
    // 在此调用的时候使用的方式是:obj.sayName(obj)
    

    但是,我们还是觉得很智障,为什么要在写过之后还要传参进去?那么我们是否可以不传参数,访问该对象呢?按照obj.sayName()即可访问呢?那么问题来了。在上述的对象中sayName中是有参数的,为什么在调用的时候不需要传入了呢?因此,js引入了this表示自己。改造成如下:

    var obj = {
        name: 'Jack',
        sayName: function(){
            console.log('I am ' + this.name)
        }
    }
    obj.sayName()   // 即可打印 I am Jack
    obj.sayName.call()  // 则打印不出Jack,此时的this为window
    obj.sayName.call(obj)  // 此时的this则为我们自己指定的obj
    

    再看一个。

    var baba = {
        name: 'Daddy',
        child: {
            name: 'Peppa',
            sayName: function() {
                console.log(this.name)
            }
        }
    }
    
    baba.child.sayName()    // Peppa
    baba.child.sayName.call(baba.child)  // 跟上述等价
    baba.child.sayName.call()    // 打印为空
    //  call不传的时候,则为undefined
    baba.child.sayName.call({name: 'Jack'})   // 则打印出Jack
    

    函数是独立的东西,不是一个附属品,只接受一个输入,并且有一个输出。在不使用call的时候,this会隐式的传进去,则不能很快速明确的确定this的指代。JS中有两个参数,一个是this,另一个是arguments。显式的this则使用call调用,隐式的this则浏览器去猜。

    从上述可以得出如下两个结论:

    1. 参数的值只有在传参的时候确定
    2. this是第一个参数 => 推断得出 this的值只有在传参的时候才能确定。

    那么我们来看看如下的this都指代什么?

    function a(){
        console.log(this)     // 在未调用的时候,this的值是未知的
    }
    a()   // 调用后this的值则为window
    
    function a(){
        'use strict'
        console.log(this)
    }
    a()  // 调用后this的值为undefined,因为是严格模式
    
    var obj = {
        sayThis: a
    }
    obj.sayThis()     // this 打印出来的为obj
    
    obj.sayThis.call()   // this为传入的第一个参数,arguments为后面的参数
    

    再看看别的this的指代情况。

    button.onclick = function(){
        console.log(this)
        this.disabled = true
        var btn = this
        $.get('./xxxx.json', function(){
            console.log(this)   // 不传参的时候,此时的this指代为window
            btn.disabled = false    // 此时的btn代表外面的this,尽量不要使用that或者_this代替
        })
    }
    // 即使this的值就算不能确定,但是this的值也是可以确定的,因为在button点击的时候一定会调用该函数
    // JS文档表示 其中的this为触发事件的元素
    // button 自己
    
    $('#button1').on('click', function(){
        console.log(this)
    })    
    // jQuery的文档告诉我们,此时的this为当前正在执行事件的元素。
    // 对于直接事件而言,this指代的是绑定事件的元素
    // button 自己
    
    $('#ul1').on('click', 'li', function(){
        console.log(this)
    })
    // jQuery的文档告诉我们,对于代理事件而言,this则代表了与selector相匹配的元素
    // li
    
    new Vue({
        data: function(){
            console.log(this)
        }
    })
    // this指代的是new出来的对象
    

    以上仅限于隐式调用时this指代的情况。 若写为button.onclick.call(1),则此时的this为传入的参数。

    为了解决this的事情,js引入了箭头函数,此时就算call也不会改变this的值。call的时候,this指代的都为外面的this。箭头函数中既没有this,也没有arguments。

    函数和对象本来没有关系,通过隐式的this才会有了关系。若使用call,则this是明确的值,即为第一个传入的参数。

    bind用法

    bind用法 bind即为创建了一个新的函数,会call原先函数的参数,传入的参数则为this和arguments。


    起源地下载网 » js中的面向对象(一)

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元