一个后端眼中的js对象和原型链

js对象

js中的类型有:

number,string,boolean,object,undefined,function

所以对象可以这么分类:

  1. 函数对象(function)
  2. 其他对象

所以函数对象可以大声唱我们不一样,既然不一样肯定得有一点不一样的烟火,函数对象的不一样在什么地方呢? 每一个函数对象都有一个prototype属性(Function.prototype除外)

作为一个傻傻的后端的我一直以为每一个对象都有一个prototype属性。每一个对象都有的是一个叫做__proto__的隐藏属性,它指向的就是对象所对应的函数对象的prototype(也就是传说中的原型对象)

后面我们再举例子来说明原型对象,我们先看一下那些是函数对象,方便理解。

那些是函数对象

    function FN() {}
    var FA = function() {}
    var FF = new Function('arg1', 'arg2', 'console.log(arg1 + arg2)');

    FF('a','b');
    console.log('typeof Object:' + typeof Object); //function
    console.log('typeof Object.prototype:' + typeof Object.prototype); //object
    console.log('typeof Function:' + typeof Function); //function
    console.log('typeof Function.prototype:' + typeof Function.prototype); //function
    console.log('typeof FN:' + typeof FN); //function
    console.log('typeof FA:' + typeof FA); //function
    console.log('typeof FF:' + typeof FF); //function

不那么精确的总结一下就是:

  1. 带function关键字的
  2. new Funtion出来的对象
  3. Funtion,Object,Function.prototype对象

这里说一下Function.prototype,因为它又是一个不一样的烟火。因为一般的函数对象的prototype都是普通对象,但是Function.prototype是一个函数对象,并且这个函数对象没有prototype属性。

所有的函数对象的__proto__都指向的是Function.prototype

可以使用:

console.log(Object.getOwnPropertyNames(Function.prototype))

打印一下Function.prototype的属性,会发现都是一下公共函数。

原型链

我们把问题简化来处理,看一个最常见的简化的原型链:

function Person(name, age) {
        this.name = name;
        this.age = age;
        this.hobby = function() {
            return '实例对象hobby';
        }
    }
    Person.hobby = function() {
        return '函数对象hobby';
    }
    Person.prototype.hobby = function(){
        return 'prototype hobby';
    }
    var p1 = new Person("tim",20);
    var p2 = new Person("alice",20);
    console.log(p1.hobby === p2.hobby);//false
    console.log(p1.__proto__ == Person.prototype);//true
    console.log(p2.__proto__ == Person.prototype);//true
    console.log(p1.__proto__ == p2.__proto__);//true
    console.log(p1.__proto__.hobby == p2.__proto__.hobby);//true
    console.log(p1.hobby());//实例对象hobby
    console.log(Person.hobby());//函数对象hobby

从前面介绍的我们知道Person是一个函数对象,既然是一个函数对象,那么Person是有prototype属性的,所以给Person的prototype的属性添加一个hobby属性也是合理的事情了。

Person是一个函数对象,那么说Person是一个对象也是合理的了,给Person添加一个hobby属性也是合理的了。

下面就要看一下关键的new关键字的行为了,我们知道Person是一个函数对象,new一个函数对象,基本上执行的就是属性拷贝,然后把new出来的对象的__proto__指向函数对象的prototype的属性。

所以上面的p1.hobby === p2.hobby是false是因为他们是2个对象中不同的属性,是2个不同的引用。

而p1.proto.hobby == p2.proto.hobby是true是因为这2个都是Person.prototype对象上的属性hobby是同一个引用。

js原型链查找方式就是在当前对象中查找这个属性,如果没有就在__proto__指向的对象中去查找,依次查找到Object.prototype结束,因为Object.prototype.proto == null

下面思考一个问题:如果把上面的:

Person.hobby = function() {
    return '函数对象hobby';
}

去掉会有问题吗?

答案是会有问题,这个问题有点绕,但是记住我们前面总结的,所有的函数对象的__proto__指向的都是Function.prototype

所有如果没有上面的代码Person.hobby()这个调用在Person函数对象中找不到hobby属性,就会在Funtion.prototype对象中找,依次找到Object.prototype,显然是找不到的。

注意原型链,不是在Person.prototype中查找,那不在Person对象的原型链。

转载于:https://my.oschina.net/u/2474629/blog/1553108

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值