【JavaScript知识总结二】全方位从5个方面深入理解JS中的原型和原型链

1. 所有的引用类型(数组,对象,函数),都是具有对象特性的,即可以自由扩展属性(除了null以外)

 // 1.引用类型可以扩展属性
    var obj = {};
    obj.a = 100;          // 对象属性的扩展
    var arr = [];
    arr.a = 100;          // 数组属性的扩展
    function fn() {
    };fn.a = 100;        // 函数属性的扩展

2. 所有的引用类型(数组、对象、函数),都有一个__proto__ 属性(隐式原型),这个属性的值是一个普通对象

 // 2. 所有的引用类型都有一个隐式原型属性
    console.log(obj.__proto__);         // 对象的隐式原型属性
    console.log(arr.__proto__);         // 数组的隐式原型属性
    console.log(fn.__proto__);          // 函数的隐式原型属性

3. 所有的函数都有一个显式原型属性(普通函数+构造函数)

 console.log({}.prototype);          // undefined  对象是没有显式原型的属性的         // undefined
    console.log([].prototype);          // undefined  数组是没有显式原型的属性的         // undefined
    console.log(fn.prototype);          // 函数的显式原型属性                            // {constructor: ƒ}

4. 所有的引用类型(数组、对象、函数),__proto__的属性值指向(完全相等)它的构造函数的“prototype”的属性值

// 4. 所有的引用类型的__proto__属性的值和它的构造函数的prototype的值是完全相等的
    // obj 的构造函数是Object(obj 的隐式原型和Object的显式原型相等的)
    console.log(obj.__proto__ === Object.prototype);                                    // true
    // arr 的构造函数是Array(arr 的隐式原型和Array的显式原型相等的)
    console.log(arr.__proto__ === Array.prototype);                                     // true
    // fn的构造函数是Function(fn的隐式原型和Function的显示原型是相等的)
    console.log(fn.__proto__ === Function.prototype);                                   // true

 

5. 当试图得到一个对象的某一个属性的时候,如果一个对象本身没有这个属性的话,就会去它的__proto__( 也就是它的构造函数中去寻找这个属性)

/**
     * 自定义的一个FOO对象
     * @param name
     * @param age
     * @constructor
     */
    function FOO(name, age) {
        this.name = name;
        this.age = age;
        this.sex = 'MALE';
    }

    // FOO.prototype是一个对象,可以给这个普通对象来扩展属性值
    FOO.prototype.alertName = function () {
        alert(this.name);
    }

    // 给所有的对象添加一个showObject的属性
    Object.prototype.showObject = function(){
        console.log('我已经找到我的祖先节点了…………', this);
    }

    // 给所有的对象添加一个showObjectName的属性信息
    Object.prototype.showObjectName = '我是祖先节点,我的名字是Object';

    // 创建实例
    var f = new FOO('zhangsan');
    // 给自己定义的对象扩展属性( 本身自己的一个属性的话,就直接输出这个属性)
    f.printName = function () {
        console.log(this.name);             // 这个this永远指向的是对象本身
    }
 // 由于已经给f这个对象扩展了一个属性(是一个函数),因此会输出自己的函数
    f.printName();

执行下面的语句,有什么结果?

f.alertName();

// 继续测试, 会先去f这个引用类型的对象上面的__proto__,也就是f的构造函数中去寻找prototype上面的属性,发现FOO.prototype上面竟然没有这个属性?
    // 怎么办?就去这个FOO对象上面的构造函数去寻找这个showObject属性,最终发现在这个对象的Object对象上面找到了这个属性,也就是showObject这个属性信息
    f.showObject();
    // 这个属性实际上Foo上面没有,那我就去父亲祖先上面寻找这个属性,最终在Object这个上面找到了这个属性信息
    console.log(f.showObjectName);
    var obj = {};       // 这里是一个语法糖,相当于是var obj = new Object();
    console.log(obj.showObject === f.showObject);       // true
    console.log(obj.showObjectName === f.showObjectName);   // true
    obj.showObject();       // this = {}, this指向的是obj
    f.showObject();         // this = FOO{},this指向的是f
    // 总结: this指向的永远是调用我的那个对象本身

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值