- 所有对象都是通过
new 函数创建 - 所有的函数也是对象
- 函数中可以有属性
- 所有对象都是引用类型
原型
- 定义:原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
- 利用原型特点和概念,可以提取共有属性。
- 对象属性的增删和原型上属性增删改查。
- 对象如何查看原型 ==> 隐式属性 proto。
- 对象如何查看对象的构造函数 ==> constructor。
prototype
- 所有函数都有一个属性:prototype,称之为函数原型
- 默认情况下,prototype是一个普通的Object对象
- 默认情况下,prototype中有一个属性,constructor,它也是一个对象,它指向构造函数本身。
proto
- 所有的对象都有一个属性:
__proto__,称之为隐式原型 - 默认情况下,隐式原型指向创建该对象的函数的原型。
当访问一个对象的成员时:
- 看该对象自身是否拥有该成员,如果有直接使用
- 在原型链中依次查找是否拥有该成员,如果有直接使用
function test() {};var obj = new test();// obj.__proto__ === test.prototypefunction A() {};var obj = new A();var obj1 = new A();obj.abc = 234;obj1.__proto__.abe = 345;console.log(obj1.abc, obj2.abc); // 234 undefinedconsole.log(obj1.__proto__.abe, obj2.__proto__.abe); // 345 345function A() {}function B() {}function create() {if (Math.random() < 0.5) {return new A();} else {return new B();}}var obj = create();//如何得到创建obj的构造函数名称console.log(obj.__proto__.constructor.name);
原型链
特殊点:
- Function的proto指向自身的prototype
- Object的prototype的proto指向null
- 图形理解原型链

function User() {}User.prototype.sayHello = function() {}var u1 = new User();var u2 = new User();console.log(u1.sayHello === u2.sayHello); //trueconsole.log(User.prototype.constructor); //User Functionconsole.log(User.prototype === Function.prototype); // falseconsole.log(User.__proto__ === Function.prototype); // trueconsole.log(User.__proto__ === Function.__proto__); // trueconsole.log(u1.__proto__ === u2.__proto__); // trueconsole.log(u1.__proto__ === User.__proto__); // falseconsole.log(Function.__proto__ === Object.__proto__); // trueconsole.log(Function.prototype.__proto__ === Object.prototype.__proto__); // falseconsole.log(Function.prototype.__proto__ === Object.prototype); // true
应用
- 注意:W3C不推荐直接使用系统成员proto
基础方法
Object.getPrototypeOf(对象)
- 获取对象的隐式原型
var fn = new Function();console.log(Object.getPrototypeOf(fn)); //就是 fn.__proto__// Object.getPrototypeOf === fn.__proto__
Object.prototype.isPrototypeOf(对象)
- 判断当前对象(this)是否在指定对象的原型链上
function Foo() {}function Bar() {}function Baz() {}Bar.prototype = Object.create(Foo.prototype);Baz.prototype = Object.create(Bar.prototype);var baz = new Baz();console.log(Baz.prototype.isPrototypeOf(baz)); // trueconsole.log(Bar.prototype.isPrototypeOf(baz)); // trueconsole.log(Foo.prototype.isPrototypeOf(baz)); // trueconsole.log(Object.prototype.isPrototypeOf(baz)); // true
对象 instanceof 函数
- 判断函数的原型是否在对象的原型链上
function Car(make, model, year) {this.make = make;this.model = model;this.year = year;}const auto = new Car('Honda', 'Accord', 1998);console.log(auto instanceof Car);// expected output: trueconsole.log(auto instanceof Object);// expected output: true
Object.create(对象)
- 创建一个新对象,其隐式原型指向指定的对象
var person = {isHuman: false,printIntroduction: function() {console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);}};var me = Object.create(person);me.name = 'Matthew'; // "name" is a property set on "me", but not on "person"me.isHuman = true; // inherited properties can be overwrittenme.printIntroduction();// expected output: "My name is Matthew. Am I human? true"
Object.prototype.hasOwnProperty(属性名)
- 判断一个对象自身是否拥有某个属性
var object1 = {};object1.property1 = 42;console.log(object1.hasOwnProperty('property1'));// expected output: trueconsole.log(object1.hasOwnProperty('toString'));// expected output: falseconsole.log(object1.hasOwnProperty('hasOwnProperty'));// expected output: false
实践
1. **类数组转换为真数组**```jsArray.prototype.slice.call(类数组);function a(value1,value2,value3){var arr = arguments;arr = Array.prototype.slice.call(arr);console.log(Array.isArray(arr)); //ture};a(1,2,3);
- 实现继承(圣杯模式)
- 默认情况下,所有构造函数的父类都是Object
//普通版function inherit(Target,Origin){var Temp = function () {};Target.prototype = new Temp();Temp.prototype = Origin.prototype;Temp.prototype.constructor = Temp;Temp.prototype.uber = Origin.prototype;}// 改版var inherit = (function(){var Temp = function () {};return function(Target,Origin){Target.prototype = new Temp();Temp.prototype = Origin.prototype;Temp.prototype.constructor = Temp;Temp.prototype.uber = Origin.prototype;}}())
<a name="d56cdcfe"></a>## 属性描述符- 属性描述符的配置参考:[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)- 属性描述符:它表达了一个属性的相关信息(元数据),它本质上是一个对象。1. 数据属性2. **存取器属性**1. 当给它赋值,会自动运行一个函数 **setter**2. 当获取它的值时,会自动运行一个函数 **getter**```javascriptvar obj = {};Object.definPrototype(obj,'name',{get(){//获取属性name 时 运行该函数console.log('读取属性name');return '小米'},set(val){/当给该属性赋值时,运行的函数//val:表示要赋的值console.log("给属性赋值为" + val);}})obj.x = '小名'; //相当于运行了 set('小名')console.log(obj.x);// console.log(obj.x);// obj.x = 'aa'; //会运行一个函数// console.log(obj.x); //会运行一个函数
