1. 所有的引用类型(数组,对象,函数),都是具有对象特性的,即可以自由扩展属性(除了null以外)
// 1.引用类型可以扩展属性
var obj = {};
obj.a = 100; // 对象属性的扩展
var arr = [];
arr.a = 100; // 数组属性的扩展
function fn() {
};fn.a = 100; // 函数属性的扩展
2. 所有的引用类型(数组、对象、函数),都有一个__proto__ 属性(隐式原型),这个属性的值是一个普通对象
// 2. 所有的引用类型都有一个隐式原型属性
console.log(obj.__proto__); // 对象的隐式原型属性
console.log(arr.__proto__); // 数组的隐式原型属性
console.log(fn.__proto__); // 函数的隐式原型属性
3. 所有的函数都有一个显式原型属性(普通函数+构造函数)
console.log({}.prototype); // undefined 对象是没有显式原型的属性的 // undefined
console.log([].prototype); // undefined 数组是没有显式原型的属性的 // undefined
console.log(fn.prototype); // 函数的显式原型属性 // {constructor: ƒ}
4. 所有的引用类型(数组、对象、函数),__proto__的属性值指向(完全相等)它的构造函数的“prototype”的属性值
// 4. 所有的引用类型的__proto__属性的值和它的构造函数的prototype的值是完全相等的
// obj 的构造函数是Object(obj 的隐式原型和Object的显式原型相等的)
console.log(obj.__proto__ === Object.prototype); // true
// arr 的构造函数是Array(arr 的隐式原型和Array的显式原型相等的)
console.log(arr.__proto__ === Array.prototype); // true
// fn的构造函数是Function(fn的隐式原型和Function的显示原型是相等的)
console.log(fn.__proto__ === Function.prototype); // true
5. 当试图得到一个对象的某一个属性的时候,如果一个对象本身没有这个属性的话,就会去它的__proto__( 也就是它的构造函数中去寻找这个属性)
/**
* 自定义的一个FOO对象
* @param name
* @param age
* @constructor
*/
function FOO(name, age) {
this.name = name;
this.age = age;
this.sex = 'MALE';
}
// FOO.prototype是一个对象,可以给这个普通对象来扩展属性值
FOO.prototype.alertName = function () {
alert(this.name);
}
// 给所有的对象添加一个showObject的属性
Object.prototype.showObject = function(){
console.log('我已经找到我的祖先节点了…………', this);
}
// 给所有的对象添加一个showObjectName的属性信息
Object.prototype.showObjectName = '我是祖先节点,我的名字是Object';
// 创建实例
var f = new FOO('zhangsan');
// 给自己定义的对象扩展属性( 本身自己的一个属性的话,就直接输出这个属性)
f.printName = function () {
console.log(this.name); // 这个this永远指向的是对象本身
}
// 由于已经给f这个对象扩展了一个属性(是一个函数),因此会输出自己的函数
f.printName();
执行下面的语句,有什么结果?
f.alertName();
// 继续测试, 会先去f这个引用类型的对象上面的__proto__,也就是f的构造函数中去寻找prototype上面的属性,发现FOO.prototype上面竟然没有这个属性?
// 怎么办?就去这个FOO对象上面的构造函数去寻找这个showObject属性,最终发现在这个对象的Object对象上面找到了这个属性,也就是showObject这个属性信息
f.showObject();
// 这个属性实际上Foo上面没有,那我就去父亲祖先上面寻找这个属性,最终在Object这个上面找到了这个属性信息
console.log(f.showObjectName);
var obj = {}; // 这里是一个语法糖,相当于是var obj = new Object();
console.log(obj.showObject === f.showObject); // true
console.log(obj.showObjectName === f.showObjectName); // true
obj.showObject(); // this = {}, this指向的是obj
f.showObject(); // this = FOO{},this指向的是f
// 总结: this指向的永远是调用我的那个对象本身