- 所有对象都是通过
new 函数
创建 - 所有的函数也是对象
- 函数中可以有属性
- 所有对象都是引用类型
原型
- 定义:原型是 function 对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
- 利用原型特点和概念,可以提取共有属性。
- 对象属性的增删和原型上属性增删改查。
- 对象如何查看原型 ==> 隐式属性 proto。
- 对象如何查看对象的构造函数 ==> constructor。
prototype
- 所有函数都有一个属性:prototype,称之为函数原型
- 默认情况下,prototype是一个普通的Object对象
- 默认情况下,prototype中有一个属性,constructor,它也是一个对象,它指向构造函数本身。
proto
- 所有的对象都有一个属性:
__proto__
,称之为隐式原型 - 默认情况下,隐式原型指向创建该对象的函数的原型。
当访问一个对象的成员时:
- 看该对象自身是否拥有该成员,如果有直接使用
- 在原型链中依次查找是否拥有该成员,如果有直接使用
function test() {};
var obj = new test();
// obj.__proto__ === test.prototype
function A() {};
var obj = new A();
var obj1 = new A();
obj.abc = 234;
obj1.__proto__.abe = 345;
console.log(obj1.abc, obj2.abc); // 234 undefined
console.log(obj1.__proto__.abe, obj2.__proto__.abe); // 345 345
function 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); //true
console.log(User.prototype.constructor); //User Function
console.log(User.prototype === Function.prototype); // false
console.log(User.__proto__ === Function.prototype); // true
console.log(User.__proto__ === Function.__proto__); // true
console.log(u1.__proto__ === u2.__proto__); // true
console.log(u1.__proto__ === User.__proto__); // false
console.log(Function.__proto__ === Object.__proto__); // true
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); // false
console.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)); // true
console.log(Bar.prototype.isPrototypeOf(baz)); // true
console.log(Foo.prototype.isPrototypeOf(baz)); // true
console.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: true
console.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 overwritten
me.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: true
console.log(object1.hasOwnProperty('toString'));
// expected output: false
console.log(object1.hasOwnProperty('hasOwnProperty'));
// expected output: false
实践
1. **类数组转换为真数组**
```js
Array.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**
```javascript
var 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); //会运行一个函数