1、所有函数都有一个特别的属性
prototype
: 显式原型属性
2、函数的prototype属性(图)
- 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象) 【即Object实例对象 {}】
- 原型对象中有一个属性constructor, 它指向函数对象 【相互引用】
3、给原型对象添加属性(一般都是方法)
- 作用: 函数的所有实例对象自动拥有原型中的属性(方法)
4、所有实例对象都有一个特别的属性
__proto__
: 隐式原型属性
5、显式原型与隐式原型的关系
- 函数的prototype: 定义函数时,被自动赋值, 值默认为{}, 即用为原型对象
- 实例对象的__proto__: 在创建实例对象时,被自动添加, 并赋值为构造函数的prototype值
- 原型对象,即为当前实例对象的父对象
6、原型链 【隐式原型链】
- 所有的实例对象都有__proto__属性, 它指向的就是原型对象
- 这样通过__proto__属性就形成了一个链的结构 ----> 原型链
- 当查找对象内部的属性/方法时, js引擎自动沿着这个原型链查找,找到返回,如果最终没找到, 返回undefined
- 作用: 查找对象的属性(方法) 【作用域:查找变量。】
- 当给对象属性赋值时,不会使用原型链, 而只是在当前对象中进行操作
- Object的原型对象是原型链尽头 【Object.prototype是实例对象,但不是一般的实例对象,console.log(Object.prototype.__proto__) // null 】
7、构造函数/原型/实例对象的关系(图解)
8、构造函数/原型/实例对象的关系2(图解)
补充:构造函数可以 new 函数名.方法() 调用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>构造函数可以 new 函数名.方法()调用</title> </head> <body> </body> </html> <script> function Fun(age) { this.age = age this.setAge = function(newAge) { this.age = newAge console.log(this.age); } } console.log(Fun.prototype); // {constructor: ƒ} Fun(0).setAge(111) // 必须要加new,new才能创建实例对象,否则报错,Cannot read property 'setAge' of undefined let f1 = new Fun(11) new Fun(22).setAge(33); // 33 (new Fun(22)).setAge(44) // 44 console.log(Fun.prototype); // {constructor: ƒ} Fun.prototype.test = function() { console.log('哈哈'); } f1.setAge(55) // 55 f1.test() // 哈哈 </script>
原型(prototype)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>01_原型(prototype)</title> </head> <body> <!-- 1. 函数的prototype属性(图) * 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象) * 原型对象中有一个属性constructor, 它指向函数对象 【相互引用】 2. 给原型对象添加属性(一般都是方法) * 作用: 函数的所有实例对象自动拥有原型中的属性(方法) --> <script type="text/javascript"> // 每个函数都有一个prototype属性, 它默认指向一个Object空对象(即称为: 原型对象) console.log(Date.prototype, typeof Date.prototype) function Fun() { //alt + shift +r(重命名rename) } console.log(Fun.prototype) // 默认指向一个Object空对象(没有我们的属性) // 原型对象中有一个属性constructor, 它指向函数对象 console.log(Date.prototype.constructor === Date) console.log(Fun.prototype.constructor === Fun) //给原型对象添加属性(一般是方法) ===>实例对象可以访问 Fun.prototype.test = function() { console.log('test()') } var fun = new Fun() fun.test() </script> </body> </html>
显式原型与隐式原型
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>02_显式原型与隐式原型</title> </head> <body> <!-- 1. 每个函数function都有一个prototype,即显式原型(属性) 2. 每个实例对象都有一个__proto__,可称为隐式原型(属性) 3. 对象的隐式原型的值为其对应构造函数的显式原型的值 4. 内存结构(图) 5. 总结: * 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象 * 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值 * 程序员能直接操作显式原型, 但不能直接操作隐式原型(ES6之前) --> <script type="text/javascript"> //定义构造函数 function Fn() { // 内部语句: this.prototype = {} } // 1. 每个函数function都有一个prototype,即显式原型属性, 默认指向一个空的Object对象 console.log(Fn.prototype) // 2. 每个实例对象都有一个__proto__,可称为隐式原型 //创建实例对象 var fn = new Fn() // 内部语句: this.__proto__ = Fn.prototype console.log(fn.__proto__) // 3. 对象的隐式原型的值为其对应构造函数的显式原型的值 console.log(Fn.prototype===fn.__proto__) // true //给原型添加方法 Fn.prototype.test = function () { console.log('test()') } //通过实例调用原型的方法 fn.test() </script> </body> </html>
**补充:构造函数有__proto__属性,实例对象没有prototype 属性**
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>5、构造函数有__proto__属性,实例对象没有prototype 属性</title> </head> <body> </body> </html> <script> function fn() { } console.log(fn.prototype); // {constructor: ƒ} // {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …} console.log(fn.prototype.__proto__); // console.log(fn.__proto__); // ƒ () { [native code] } f1 = new fn() console.log(f1.__proto__ === fn.prototype); // true console.log(f1.prototype); // undefined </script>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>03_原型链</title> </head> <body> <!-- 1. 原型链(图解) * 访问一个对象的属性时, * 先在自身属性中查找,找到返回 * 如果没有, 再沿着__proto__这条链向上查找, 找到返回 * 如果最终没找到, 返回undefined * 别名: 隐式原型链 * 作用: 查找对象的属性(方法) 【作用域:查找变量。】 2. 构造函数/原型/实体对象的关系(图解) 3. 构造函数/原型/实体对象的关系2(图解) --> <script type="text/javascript"> // console.log(Object) //console.log(Object.prototype) console.log(Object.prototype.__proto__) // null function Fn() { this.test1 = function() { console.log('test1()') // test1() } } // 对象就只有一个/一份,所以这句代码虽然在添加test2方法前,但是依然会输出test2 console.log(Fn.prototype) // {constructor: ƒ} Fn.prototype.test2 = function() { console.log('test2()') // test2() } var fn = new Fn(); fn.test1(); fn.test2(); console.log(fn.toString()); // [object Object] console.log(fn.test3); // undefined // fn.test3() // 报错 // 1. 函数的显式原型指向的对象,默认是空Object实例对象(但Object不满足) console.log(Fn.prototype instanceof Object) // true console.log(Object.prototype instanceof Object) // false console.log(Function.prototype instanceof Object) // true // 2. 所有函数都是Function的实例(包含Function) console.log(Function.__proto__ === Function.prototype) // true // 3. Object的原型对象是原型链尽头 console.log(Object.prototype.__proto__) // null </script> </body> </html>
来源:https://www.cnblogs.com/jianjie/p/12242865.html