原型、原型链

1. prototype
每个函数都有一个prototype属性,被称为显示原型
2._ _proto_ _
每个实例对象都会有_ _proto_ _属性,其被称为隐式原型
每一个实例对象的隐式原型_ _proto_ 属性指向自身构造函数的显式原型prototype
3. constructor
每个prototype原型都有一个constructor属性,指向它关联的构造函数。
4. 原型链
获取对象属性时,如果对象本身没有这个属性,那就会去他的原型_ _proto_ _上去找,如果还查不到,就去找原型的原型,一直找到最顶层(Object.prototype)为止。Object.prototype对象也有_ _proto_ _属性值为null。

function Fun(){
            }
//            我创造了一个函数Fn
//            这个函数由Function生成(Function作为构造函数)
            var fn=new Fun()
//            我创建了一个函数fn
//            这个函数由构造函数Fun生成


            console.log(fn.__proto__===Fun.prototype)    //true
//            fn的__proto__指向其构造函数Fun的prototype
            console.log(Fun.__proto__===Function.prototype)        //true
//            Fun的__proto__指向其构造函数Function的prototype
            console.log(Function.__proto__===Function.prototype)    //true
//            Function的__proto__指向其构造函数Function的prototype
//            构造函数自身是一个函数,他是被自身构造的
            console.log(Function.prototype.__proto__===Object.prototype)    //true
//            Function.prototype的__proto__指向其构造函数Object的prototype
//            Function.prototype是一个对象,同样是一个方法,方法是函数,所以它必须有自己的构造函数也就是Object
            console.log(Fun.prototype.__proto__===Object.prototype)         //true
//             与上条相同
//             此处可以知道一点,所有构造函数的的prototype方法的__都指向__Object.prototype(除了....Object.prototype自身)
            console.log(Object.__proto__===Function.prototype)        //true
//            Object作为一个构造函数(是一个函数对象!!函数对象!!),所以他的__proto__指向Function.prototype
            console.log(Object.prototype.__proto__===null)        //true
//            Object.prototype作为一切的源头,他的__proto__是null

//            下面是一个新的,额外的例子

            var obj={}
//            创建了一个obj
            console.log(obj.__proto__===Object.prototype)        //true
//            obj作为一个直接以字面量创建的对象,所以obj__proto__直接指向了Object.prototype,而不需要经过Function了!!

//            下面是根据原型链延伸的内容
//            还有一个上文并未提到的constructor,  constructor在原型链中,是作为对象prototype的一个属性存在的,它指向构造函数(由于主要讲原型链,这个就没在意、);

            console.log(obj.__proto__.__proto__===null)        //true
            console.log(obj.__proto__.constructor===Object)        //true
            console.log(obj.__proto__.constructor.__proto__===Function.prototype)        //true
            console.log(obj.__proto__.constructor.__proto__.__proto__===Object.prototype)    //true
            console.log(obj.__proto__.constructor.__proto__.__proto__.__proto__===null)        //true
            console.log(obj.__proto__.constructor.__proto__.__proto__.constructor.__proto__===Function.prototype)    //true


//            以上,有兴趣的可以一一验证  F12搞起.
<think>好的,我现在需要帮助用户理解JavaScript中的原型原型链。用户要求详细的示例和解析,所以我得先理清楚这两个概念的基本定义和它们之间的关系。首先,原型是什么?根据引用[1],原型是每个JavaScript对象都有的一个内部属性,用于实现属性和方法的继承。构造函数有prototype属性,指向原型对象,而实例对象通过__proto__访问原型。 接下来,原型链是怎么形成的呢?引用[2]提到,当访问一个对象的属性时,如果对象本身没有该属性,就会沿着原型链向上查找,直到找到或到达原型链末端(null)。这个过程是通过每个对象的__proto__连接起来的链条。例如,实例的__proto__指向构造函数的prototype,而构造函数的prototype的__proto__可能指向Object.prototype,最终到null,形成一个链式结构。 用户可能想知道如何通过代码来验证这些概念。我需要举一个构造函数的例子,比如创建一个Person构造函数,然后生成实例,并展示原型链的层级。例如,Person.prototype是实例的原型,而Person.prototype本身也是一个对象,它的原型是Object.prototype。这样,当实例访问toString方法时,会沿着原型链找到Object.prototype的toString。 然后,继承是如何通过原型链实现的?根据引用[3],可以通过将子类的prototype指向父类的实例来实现继承。例如,Student继承Person,将Student.prototype = new Person(),这样Student的实例就能访问Person的属性和方法。同时,还需要修正constructor的指向,避免引用混乱。 用户可能还会关心ES6中的class语法和原型的关系。引用[4]指出,class本质上是原型继承的语法糖。使用class定义类时,其方法会被添加到原型对象上,extends关键字则基于原型链实现继承。这样,class让原型继承更直观,但底层机制不变。 需要确保提供的示例代码正确且易于理解。比如,定义构造函数、添加方法到原型、创建实例并调用方法。同时,展示原型链的查找过程,比如使用hasOwnProperty检查属性是否在实例上,以及instanceof运算符的原理。 用户可能的问题包括原型链的终点是什么,如何判断属性是实例自身还是继承来的,以及如何实现继承的不同方法。在回答时,要分点清晰,结合代码示例和引用资料中的概念,确保准确性和易懂性。 最后,生成的相关问题需要覆盖原型链的应用、与class的关系、性能影响、常见错误等,帮助用户进一步深入理解。</think>### JavaScript 原型原型链详解 #### 一、原型(Prototype) 1. **基本概念** JavaScript 中每个对象都有一个隐藏属性 `[[Prototype]]`(通过 `__proto__` 访问),指向其原型对象。构造函数通过 `prototype` 属性关联原型对象,实例通过 `__proto__` 继承原型属性和方法[^1][^4]。 ```javascript function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log(`Hello, ${this.name}!`); }; const alice = new Person("Alice"); alice.sayHello(); // 调用原型方法 [^1] ``` 2. **原型层级** 实例的 `__proto__` 指向构造函数的 `prototype`,而构造函数的 `prototype` 本身也是对象,其 `__proto__` 指向 `Object.prototype`,最终原型链顶端为 `null`。 ```javascript console.log(alice.__proto__ === Person.prototype); // true console.log(Person.prototype.__proto__ === Object.prototype); // true console.log(Object.prototype.__proto__); // null [^2] ``` --- #### 二、原型链(Prototype Chain) 1. **属性查找机制** 当访问对象属性时,JavaScript 会按以下顺序查找: - 对象自身属性 - 沿原型链逐级向上查找(通过 `__proto__`) - 直到找到属性或到达 `null`[^3] ```javascript console.log(alice.hasOwnProperty("name")); // true(自身属性) console.log(alice.hasOwnProperty("sayHello")); // false(继承属性) ``` 2. **原型链继承示例** 通过修改原型链实现继承: ```javascript function Student(name, grade) { Person.call(this, name); this.grade = grade; } Student.prototype = Object.create(Person.prototype); // 继承原型 Student.prototype.constructor = Student; // 修正构造函数指向 const bob = new Student("Bob", 3); bob.sayHello(); // 继承自Person原型 ``` --- #### 三、关键特性与用法 1. **原型链的终点** 所有原型链的终点是 `Object.prototype`,其 `__proto__` 为 `null`。 2. **判断原型关系** - `instanceof`:检测构造函数是否在原型链上 ```javascript console.log(bob instanceof Student); // true console.log(bob instanceof Person); // true ``` - `Object.getPrototypeOf()`:获取对象的原型 ```javascript console.log(Object.getPrototypeOf(bob) === Student.prototype); // true ``` 3. **原型污染与防御** 修改 `Object.prototype` 会影响所有对象,需谨慎操作: ```javascript Object.prototype.customMethod = () => {}; // 所有对象均可访问 ``` --- #### 四、ES6 Class 与原型链 `class` 是原型继承的语法糖,本质仍基于原型链: ```javascript class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } } class Dog extends Animal { speak() { super.speak(); console.log(`${this.name} barks.`); } } const dog = new Dog("Rex"); dog.speak(); // 继承并扩展方法 ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值