创建对象和原型链
1.创建对象的三种方式
- 字面量
- 构造函数
Object.create
//1.字面量方式
var obj1 = {name: 'TOM'}
//上下二者等价
var obj2 = new Object(name: `TOM`)
//2.构造函数方式
var M = function (name){
this.name = name
}
var obj3 = new M('TOM')
//2.Object.create方式
var p = {name:'TOM'}
var obj4 = Object.create(p)//原型链连接
//obj4是实例,name是p原型的属性,构造函数是Object
2.原型、构造函数、实例和原型链
构造函数
为什么需要原型?
看看以下例子..
function Person(name, age, gender) {
this.name = name
this.age = age
this.gender = gender
this.sayName = function () {
alert(this.name);
}
}
var per1 = new Person("孙悟空", 18, "男");
var per2 = new Person("唐僧", 78, "男");
这样创建对象,每创建一个实例对象,该实例对象就会自带一个sayName方法,如果创建成千上万个实例对象,就会有成千上万个sayName方法。那么为什么不可以把所有实例对象都拥有的方法放在一个地方呢?------原型
从而就诞生了原型!
原型
原型对象就相当于一个公共区域,所有同一个类中的实例对象都可以访问到它
构造函数把所有实例拥有的方法放到了原型对象上面,并且通过prototype可以访问到原型对象。
原型链
任何一个实例都可以通过原型链找到它上面的原型,该原型对象中的方法和属性可以被所有原型实例共享。
__proto__:每个对象数据类型天生自带__proto__
原型链中有一个constructor属性,它指向构造函数对象。
例题
function User() {}
User.prototype.sayHello = function () {};
var u1 = new User();
var u2 = new User();
console.log(u1.sayHello === u2.sayHello); //true
/**
* u1的__proto__和u2的__proto__都是指向构造函数User的prototype,
* User.prototype的身上有sayHello方法,所以结果为true
*/
console.log(User.prototype === Function.prototype); //false
/**
* User.prototype的__proto__指向Function.prototype,所以结果为false
*/
console.log(User.__proto__ === Function.prototype); //true
/**
*User是一个构造函数,那么它的隐式原型就指向Function.prototype
*/
console.log(User.__proto__ === Function.__proto__); //true
/**
*
*/
console.log(u1.__proto__ === u2.__proto__); //true
/**
* u1的__proto__和u2的__proto__都是指向构造函数User的prototype,所以结果为true
*/
console.log(u1.__proto__ === User.__proto__); //false
/**
* u1.__proto__指向User.prototype,而User.__proto__指向Function.prototype
*/
console.log(Function.__proto__ === Object.__proto__); //true
/**
* Function.__proto__是指向Object的
* Object.__proto__指向Object.prototype
*/
console.log(Function.prototype.__proto__ === Object.prototype.__proto__); //false
/**
* 因为在JS里面万物皆对象,而Function又是对象的一个分支,所以Function的显式原型就是Object
* Function.prototype.__proto__指向Object.prototype
* Object.prototype.__proto__指向null
*/
console.log(Function.prototype.__proto__ === Object.prototype); //true
/**
* Function.prototype指向Object,再加上__proto__就是指向Obeject.prototype
*/
3.instanceof
const obj = {}
const arr = []
console.log(typeof obj) //Object
console.log(typeof arr) //Object
以上二者都会打印Object,因为在JavaScript中万物皆对象,Array也属于对象,这样就分辨不出来对象和数组。
那么这里可以用到instanceof关键字
const obj = {}
const arr = []
console.log(obj instanceof Array) //false
console.log(arr instanceof Array) //true
instanceof的作用:判断实例属于哪个构造函数
instanceof的原理:判断实例对象的__proto__属性和构造函数的prototype属性是否为同一个引用。
注意
在多层原型链上面,如果在第一层原型没有找到就会往上继续找一直找到最后的原型。只要在这条原型链上可以找到实例是某一构造函数的,那么就会返回true;否则返回false。
另外,instancerof关键字并不能判断基本数据类型。
\