原型链
这里只是通过一些案例补充之前对原型,原型链,instanceof的细节。
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// // 函数构造器
// console.log(Function); //ƒ Function() { [native code] }
// // 对象构造器
// console.log(Object); //ƒ Object() { [native code] }
// // 数组构造器
// console.log(Array); //ƒ Array() { [native code] }
// // 字符串构造器
// console.log(String); //ƒ String() { [native code] }
// // 数字构造器
// console.log(Number); //ƒ Number() { [native code] }
// // 布尔构造器
// console.log(Boolean); //ƒ Boolean() { [native code] }
// 定义一个函数(构造函数)Father
function Father() { }
// 使用构造函数创建对象father
var father = new Father()
// 使用字面量形式创建对象
var car = {}
// 使用Object构造器创建对象
var home = new Object()
// 使用字面量形式创建一个数组arr
var arr = [1, 2, 3]
/**
* prototype原型对象,即原型对象也是对象,是对象就可以通过原型链继承其原型上的属性和方法,
* prototype是对象,所以prototype也可通过原型链继承其原型上的属性和方法
*/
/**
* 每个对象都可以通过原型链访问(或者说继承)其原型链上的属性和方法
* 使用构造函数创建的对象,可以通过原型链继承这个构造函数上的属性和方法(说白了就是这个构造函数的原型)
* */
console.log(father.__proto__ === Father.prototype); //true
/**
* 这个构造函数的原型对象,即Father.prototype,也可通过原型链继续继承它(Father.prototype)原型链上的属性和方法
*/
console.log(Father.prototype.__proto__); //true
console.log(Father.prototype.__proto__ === Object.prototype); //true
console.log(Father.prototype.constructor === Father); //true
// 通过构造函数创建的对象,可以通过原型链访问其原型
console.log(father.__proto__) //true
// 通过字面量形式创建的对象,其本身就继承Object.prototype
console.log(car.__proto__.constructor === Object);
console.log(arr.__proto__ === Array.prototype); //true
// 同理,函数实际也是一个对象,因此,函数也可以通过其原型链访问其原型
console.log(Function.__proto__ === Function.prototype);//true
console.log(Function.__proto__ === Function.prototype);//true
console.log(Function);
console.log(Function.prototype); //ƒ () { [native code] }
/**
* 所有函数都有自己的prototype
*/
console.log(Object.prototype); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Array.prototype); //[constructor: ƒ, concat: ƒ, copyWithin: ƒ, fill: ƒ, find: ƒ, …]
console.log(String.prototype); //String {"", constructor: ƒ, anchor: ƒ, big: ƒ, blink: ƒ, …}
console.log(Number.prototype); //Number {0, constructor: ƒ, toExponential: ƒ, toFixed: ƒ, toPrecision: ƒ, …}
console.log(Boolean.prototype); //Boolean {false, constructor: ƒ, toString: ƒ, valueOf: ƒ}
console.log(Array.prototype === Function.prototype); //false
console.log(String.prototype === Function.prototype); //false
console.log(Number.prototype === Function.prototype); //false
console.log(Object.__proto__ === Function.prototype); //true
console.log(Array.__proto__ === Function.prototype); //true
console.log(Function.__proto__ === Function.prototype);//true
console.log(String.__proto__ === Function.prototype); //true
console.log(Number.__proto__ === Function.prototype); //true
console.log(Boolean.__proto__ === Function.prototype); //true
/**
* Object.protype是原型链的顶端,它在往上就是null
* 其余所有对象(Array,String,Number...)会通过原型链继承Object.prototype
*/
console.log(Object.prototype
.__proto__
); //null
console.log(Array.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(String.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Number.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Boolean.prototype
.__proto__
); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log(Array.prototype.__proto__ === Object.prototype); //true
console.log(String.prototype.__proto__ === Object.prototype); //true
console.log(Number.prototype.__proto__ === Object.prototype); //true
console.log(Boolean.prototype.__proto__ === Object.prototype); //true
console.log(Array); //ƒ Array() { [native code] }
console.log(Array.prototype); //prototype是原型对象,对象就有__proto__。它还有constructor保存本身,还有本身的属性以及方法
console.log(Array.prototype.constructor === Array); //true
console.log(Array.__proto__ === Function.prototype); //true
console.log(Array.prototype.__proto__); //{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
console.log('--------------');
/**
* 所有对象都可以通过new创建,比如数组:new Array();对象:new Object();函数:new Function();字符串:new String()....
* new后面的叫构造函数,即Array();Object();Function();String()...都是构造函数
* 构造函数也是函数,那么就有一个问题,js所有东西都是对象的话,是先有对象还是现有构造函数?(因为对象也是new出来的)
* 如果是先有函数,再通过函数new产生的对象,那么函数又是怎么来的?所以就类似:先有鸡还是现有鸡蛋的问题。
* 所以,函数是怎么来的?这个解释了就说的通了
* */
/**
* 函数有prototype,对象有__proto__
* 函数可以通过prototype.constructor访问自己构造它的函数
* 对象可以通过__proto__继承上层的prototype
*/
console.log(Function instanceof Object); //true
// 函数就有prototype
console.log(Function.prototype instanceof Object); //true
console.log(Function.prototype.__proto__ instanceof Object); //fasle
// 函数也是一个对象,对象就有__proto__,所以函数有__proto__
console.log(Function.__proto__ instanceof Object); //true
console.log(Function.__proto__ instanceof Object); //true
console.log(Function.__proto__.__proto__ instanceof Object); //false
console.log(Function.__proto__.__proto__ instanceof Object); //false
console.log(Function.constructor === Function); //true
console.log('-----------------------');
var cat = {}
function Dog() { }
var dog = new Dog()
console.log(cat.__proto__ === Function.prototype); //false
console.log(dog.__proto__ === Function.prototype); //false
console.log(cat.__proto__ === Object.prototype); //true
console.log(dog.__proto__ === Object.prototype); //false
console.log(cat.__proto__ === dog.__proto__); //false
console.log(dog.__proto__ === Dog.prototype); //true
</script>
</body>
</html>
图解
这里引用网上的图,个人也认为这张图很具体很全面。