原型和原型链超细讲解 prototype __proto__

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    
</body>
<script>
    // 1、原型就是prototype,每一个函数(除了箭头函数)都有一个原型,原型的作用是为了实现js三大特性“继承、封装、多态”中的继承。
    // 2、可以把它理解成一个js的内置属性,使用起来
    var obj = {
        a: 1
    }
    // 就像obj.a一样
    // 3、我来声明一个函数
    function one () {}
    console.log("one::: ", one.prototype);
    // 4、就是这样,就像你每创建一个obj就有一个a一样(假设),原型就是你每创建一个函数,函数就会自动加一个叫做prototype的属性。

    // 5、接下来看一下是如何实现继承的。

    // 6、首先创建一个构造函数Two,是不是发现和one没什么不同,是的,构造函数和普通函数就是一样的。不同点如下。
        // 6-1、构造函数里面的内容和普通的函数不一样。
        // 6-2、一般名称大写开头,目的就是为了区分构造和普通函数。
        // 6-3、用法不一样,构造函数用new来调用,普通函数直接调用。
    function Two(num) {    // 构造函数
        this.num = num
    }

    const two = new Two(1)
    console.log(two.num) // 1

    function three(num) {   // 普通函数
        return num + 1
    }
    three(1) // 2

    // 7、实现继承
    function 人类生成机(name, age, sex) {
        this.name = name
        this.age = age
        this.sex = sex === 1 ? '男' : '女'
    }
    const= new 人类生成机('李强', 18, 1); console.log("李::: ",.name,.age,.sex); //  李::: 李强 18 男
    const= new 人类生成机('吕雪', 22, 2)
    const= new 人类生成机('张芸', 18, 2)
    const= new 人类生成机('杨过', 40, 1)

    // 8、是不是感觉普通函数也能做到这些,重点来了
    人类生成机.prototype.身高 = 180
    console.log("李.身高::: ",.身高);    // 180
    console.log("吕.身高::: ",.身高);    // 180
    console.log("张.身高::: ",.身高);    // 180
    console.log("杨.身高::: ",.身高);    // 180

    // 9、只要是通过new出来的人,在其prototype(原型)上加一个属性,所有人就都有了这个属性,明白这个为什么叫原型了吧。
    // 10、进阶一下
    人类生成机.prototype.getWeight = function () {
        if (this.name === '李强') {
            return '傻大个'
        } else {
            return '超级苗条'
        }
    }

    console.log("李.体重::: ",.getWeight());   // 傻大个
    console.log("吕.体重::: ",.getWeight());   // 超级苗条
    console.log("张.体重::: ",.getWeight());   // 超级苗条
    console.log("杨.体重::: ",.getWeight());   // 超级苗条

    // 11、看见没,方法也被继承了,这就是继承的作用。
    
    // 12、但是这在开发中有什么用呢?再进阶一下。
    console.log("Array.prototype::: ", Array.prototype);
    // console.log("String.prototype::: ", String.prototype);
    // console.log("Object.prototype::: ", Object.prototype);

    // 下面是数组原型上的方法

    // concat: ƒ concat() 
    // fill: ƒ fill()
    // filter: ƒ filter()
    // find: ƒ find()
    // findIndex: ƒ findIndex()
    // flat: ƒ flat()
    // flatMap: ƒ flatMap()
    // pop: ƒ pop()
    // push: ƒ push()
    // reduce: ƒ reduce()
    // reduceRight: ƒ reduceRight()
    // reverse: ƒ reverse()
    // shift: ƒ shift()
    // slice: ƒ slice()
    // some: ƒ some()
    // sort: ƒ sort()
    // splice: ƒ splice()

    // 看到了吗,数组的原型上有巨多的方法,我只复制了一部分。
    // 但是我们如果使用这些方法时要new一个 Array(), new Object(), new String()才能使用prototype上的方法的话,那就太麻烦了。
    // 所以每写一个[], 一个{}, 一个"",这都叫做字面量。实际上就是js通过特定的字面量new了一个实例对象。
    // 虽然我们只是通过字面量{}创建了对象,但是js还是通过隐式的new创建的,看不见罢了。

    [1, 2, 3].filter(item => item > 2) // 3
    // 这就是原型!


    // 接下来进入第二关,原型链。
    // 1、上面说了,每一个函数(除箭头函数)都有一个原型,凭什么就函数特殊,对象也有的。
    // 2、每一个对象都有一个__proto__属性,这个属性就叫原型链。
    // 3、为什么叫原型链呢?肯定和原型有关,因为__proto__指向构造函数的prototype。可能有点懵,再来例子。
    const arr = [1, 2, 3]
    // 104行说了,字面量,也是new出来的不管是数组、对象还是字符串,我们把new出来的东西统一称为实例化对象,是对象,就有__proto__,就有原型链。
    // 看一下arr的原型链到底指向谁。
    console.log(arr.__proto__ === Array.prototype) // true
    console.log("Array.prototype::: ", Array.prototype); // 一大堆方法
    console.log("arr.__proto__::: ", arr.__proto__);     // 一大堆方法
    console.log("Array.prototype.filter::: ", Array.prototype.filter); // 数组filter方法
    console.log("arr.__proto__.filter::: ", arr.__proto__.filter); // 数组filter方法

    // 所以说,[]实际上是被new出来的,被new构造函数的就是Array。
    // 但是为什么arr.filter就能直接调用方法呢?而不是用arr.__proto__.filter,这就是js的问题了,js为了方便,就把原型链给省略了。
    // 要是没有省略,也就没有你为什么不懂原型链的问题了。
    // 这,就是原型链!

    // 看到这里了,再去看一下57行。就又加深一点印象了。
    console.log("杨.身高::: ",.身高);    // 180  省略原型链的
    console.log("杨.身高::: ",.__proto__.身高);    // 180    没省略原型链的


</script>
</html>



  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
prototype和__proto__都与JavaScript中的原型链相关。 1. prototype是一个函数特有的属性,它指向一个对象,该对象是使用该函数作为构造函数创建的所有实例的原型。通过原型链,实例可以访问构造函数的原型中定义的属性和方法。 例如,我们有一个构造函数Person: ```javascript function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log('Hello, ' + this.name + '!'); }; var person1 = new Person('Alice'); person1.sayHello(); // 输出 "Hello, Alice!" ``` 在上面的例子中,Person.prototype是一个对象,它包含了我们想要共享给所有Person实例的属性和方法。 2. __proto__是每个对象都有的属性,它指向该对象的原型。通过__proto__,对象可以访问自己的原型中定义的属性和方法。 例如,我们再使用上面的Person构造函数创建一个person2对象: ```javascript var person2 = new Person('Bob'); person2.sayHello(); // 输出 "Hello, Bob!" ``` 在上面的例子中,person2.__proto__指向Person.prototype,这样person2就可以调用Person.prototype中定义的sayHello方法。 虽然__proto__属性在现代JavaScript中已经被废弃,但仍然可以在一些老旧的浏览器和环境中使用。推荐使用Object.getPrototypeOf()来获取对象的原型,例如: ```javascript var proto = Object.getPrototypeOf(person2); proto === Person.prototype; // true ``` 总结:prototype是构造函数的属性,指向构造函数的原型对象;而__proto__是每个对象都有的属性,指向该对象的原型

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值