• 所有对象都是通过new 函数创建
  • 所有的函数也是对象
    • 函数中可以有属性
  • 所有对象都是引用类型

原型

  1. 定义:原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
  2. 利用原型特点和概念,可以提取共有属性。
  3. 对象属性的增删和原型上属性增删改查。
  4. 对象如何查看原型 ==> 隐式属性 proto
  5. 对象如何查看对象的构造函数 ==> constructor。

prototype

  • 所有函数都有一个属性:prototype,称之为函数原型
  • 默认情况下,prototype是一个普通的Object对象
  • 默认情况下,prototype中有一个属性,constructor,它也是一个对象,它指向构造函数本身。

proto

  • 所有的对象都有一个属性:__proto__,称之为隐式原型
  • 默认情况下,隐式原型指向创建该对象的函数的原型。

当访问一个对象的成员时:

  1. 看该对象自身是否拥有该成员,如果有直接使用
  2. 在原型链中依次查找是否拥有该成员,如果有直接使用
  1. function test() {};
  2. var obj = new test();
  3. // obj.__proto__ === test.prototype
  4. function A() {};
  5. var obj = new A();
  6. var obj1 = new A();
  7. obj.abc = 234;
  8. obj1.__proto__.abe = 345;
  9. console.log(obj1.abc, obj2.abc); // 234 undefined
  10. console.log(obj1.__proto__.abe, obj2.__proto__.abe); // 345 345
  11. function A() {}
  12. function B() {}
  13. function create() {
  14. if (Math.random() < 0.5) {
  15. return new A();
  16. } else {
  17. return new B();
  18. }
  19. }
  20. var obj = create();
  21. //如何得到创建obj的构造函数名称
  22. console.log(obj.__proto__.constructor.name);

原型链

特殊点:

  1. Function的proto指向自身的prototype
  2. Object的prototype的proto指向null
  • 图形理解原型链

链条的全貌.jpg

  1. function User() {}
  2. User.prototype.sayHello = function() {}
  3. var u1 = new User();
  4. var u2 = new User();
  5. console.log(u1.sayHello === u2.sayHello); //true
  6. console.log(User.prototype.constructor); //User Function
  7. console.log(User.prototype === Function.prototype); // false
  8. console.log(User.__proto__ === Function.prototype); // true
  9. console.log(User.__proto__ === Function.__proto__); // true
  10. console.log(u1.__proto__ === u2.__proto__); // true
  11. console.log(u1.__proto__ === User.__proto__); // false
  12. console.log(Function.__proto__ === Object.__proto__); // true
  13. console.log(Function.prototype.__proto__ === Object.prototype.__proto__); // false
  14. console.log(Function.prototype.__proto__ === Object.prototype); // true

应用

  • 注意:W3C不推荐直接使用系统成员proto

基础方法

Object.getPrototypeOf(对象)

  • 获取对象的隐式原型
  1. var fn = new Function();
  2. console.log(Object.getPrototypeOf(fn)); //就是 fn.__proto__
  3. // Object.getPrototypeOf === fn.__proto__

Object.prototype.isPrototypeOf(对象)

  • 判断当前对象(this)是否在指定对象的原型链上
  1. function Foo() {}
  2. function Bar() {}
  3. function Baz() {}
  4. Bar.prototype = Object.create(Foo.prototype);
  5. Baz.prototype = Object.create(Bar.prototype);
  6. var baz = new Baz();
  7. console.log(Baz.prototype.isPrototypeOf(baz)); // true
  8. console.log(Bar.prototype.isPrototypeOf(baz)); // true
  9. console.log(Foo.prototype.isPrototypeOf(baz)); // true
  10. console.log(Object.prototype.isPrototypeOf(baz)); // true

对象 instanceof 函数

  • 判断函数的原型是否在对象的原型链上
  1. function Car(make, model, year) {
  2. this.make = make;
  3. this.model = model;
  4. this.year = year;
  5. }
  6. const auto = new Car('Honda', 'Accord', 1998);
  7. console.log(auto instanceof Car);
  8. // expected output: true
  9. console.log(auto instanceof Object);
  10. // expected output: true

Object.create(对象)

  • 创建一个新对象,其隐式原型指向指定的对象
  1. var person = {
  2. isHuman: false,
  3. printIntroduction: function() {
  4. console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
  5. }
  6. };
  7. var me = Object.create(person);
  8. me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"
  9. me.isHuman = true; // inherited properties can be overwritten
  10. me.printIntroduction();
  11. // expected output: "My name is Matthew. Am I human? true"

Object.prototype.hasOwnProperty(属性名)

  • 判断一个对象自身是否拥有某个属性
  1. var object1 = {};
  2. object1.property1 = 42;
  3. console.log(object1.hasOwnProperty('property1'));
  4. // expected output: true
  5. console.log(object1.hasOwnProperty('toString'));
  6. // expected output: false
  7. console.log(object1.hasOwnProperty('hasOwnProperty'));
  8. // expected output: false

实践

  1. 1. **类数组转换为真数组**
  2. ```js
  3. Array.prototype.slice.call(类数组);
  4. function a(value1,value2,value3){
  5. var arr = arguments;
  6. arr = Array.prototype.slice.call(arr);
  7. console.log(Array.isArray(arr)); //ture
  8. };
  9. a(1,2,3);
  1. 实现继承(圣杯模式)
  • 默认情况下,所有构造函数的父类都是Object
  1. //普通版
  2. function inherit(Target,Origin){
  3. var Temp = function () {};
  4. Target.prototype = new Temp();
  5. Temp.prototype = Origin.prototype;
  6. Temp.prototype.constructor = Temp;
  7. Temp.prototype.uber = Origin.prototype;
  8. }
  9. // 改版
  10. var inherit = (function(){
  11. var Temp = function () {};
  12. return function(Target,Origin){
  13. Target.prototype = new Temp();
  14. Temp.prototype = Origin.prototype;
  15. Temp.prototype.constructor = Temp;
  16. Temp.prototype.uber = Origin.prototype;
  17. }
  18. }())
  1. <a name="d56cdcfe"></a>
  2. ## 属性描述符
  3. - 属性描述符的配置参考:[https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty)
  4. - 属性描述符:它表达了一个属性的相关信息(元数据),它本质上是一个对象。
  5. 1. 数据属性
  6. 2. **存取器属性**
  7. 1. 当给它赋值,会自动运行一个函数 **setter**
  8. 2. 当获取它的值时,会自动运行一个函数 **getter**
  9. ```javascript
  10. var obj = {};
  11. Object.definPrototype(obj,'name',{
  12. get(){
  13. //获取属性name 时 运行该函数
  14. console.log('读取属性name');
  15. return '小米'
  16. },
  17. set(val){
  18. /当给该属性赋值时,运行的函数
  19. //val:表示要赋的值
  20. console.log("给属性赋值为" + val);
  21. }
  22. })
  23. obj.x = '小名'; //相当于运行了 set('小名')
  24. console.log(obj.x);
  25. // console.log(obj.x);
  26. // obj.x = 'aa'; //会运行一个函数
  27. // console.log(obj.x); //会运行一个函数