1.基本类型不是对象(boolean、undefined、number、string)
2.引用类型都是对象(Array,function ,Object)
3.对象是通过函数创建,并且强调,对象字面量也是通过函数创建,举例说明,ES6继承的语法糖
4.函数有的是显式原型prototype
5.对象有的是隐式原型__proto__ 和构造器 constructor
6.但是由于JS中函数也是一种对象,所以函数也拥有__proto__和constructor
7.__proto__ 属性,它是对象所独有的,可以看到__proto__属性都是由一个对象指向一个对象.
它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null(可以理解为原始人。。。),再往上找就相当于在null上取值,会报错(可以理解为,再往上就已经不是“人”的范畴了,找不到了,到此结束。
8.prototype属性,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象,它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。
8.constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数(本身拥有或继承而来,继承而来的要结合__proto__属性查看会更清楚点
举栗:
class Person {
constructor(name) {
this.name = name;
}
}
var xiaoming = new Person('张三');
console.log(xiaoming);
输出结果:
Person {name: "张三"}
name: "张三"
__proto__: Object
__proto__就是由xiaoming(实例对象)指向Person 对象。
举栗:
console.log(xiaoming.__proto__);
输出结果:
{constructor: ƒ}
constructor: ƒ Person(name)
arguments: (...)
caller: (...)
length: 1
name: "Person"
prototype: {constructor: ƒ}
__proto__: ƒ ()
[[FunctionLocation]]: index.vue?0dbc:133
[[Scopes]]: Scopes[3]
__proto__: Object
里面的构造器指向的是Person里面的构造函数,因为是函数,所以有prototype(显式原型)
举栗:
console.log(xiaoming.__proto__.__proto__);
输出的是:
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()
寻找构造函数的原型,因为函数也是一个引用类型,所以构造函数指向Object对象
举栗:
console.log(xiaoming.__proto__.__proto__.__proto__);
已无隐式原型,内存地址指向空对象指针,输出null