<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 先创建一个构造函数
function Man(name, age, height) {
this.name = name;
this.age = age;
this.height = height;
// this.goHome = function () {
// console.log('这里有一个' + this.age + '的男人,叫' + this.name + '身高是' + this.height + 'cm');
// } 方法写在这里 console.log(Boy.goHome == Jack.goHome); 的结果是false
}
// 为Man这个构造函数添加它的实例对象要调用的方法 也就是函数(也就是实例对象的动作 就是方法)
// 为了解决实例对象调用的方法地址空间不一样问题 所以方法写在构造函数的原型里面也就是prototype里面;;;
// 每一个函数都会与生俱来一个原型prototype对象空间 ,构造函数 也是函数 所以构造函数也有 并且是装方法的空间
// 每一个对象与生俱来都会有一个__proto__对象(这个 对象里面的 一些方法和属性其所在的对象是可以直接调用的,
// 当对象在自己的属性和方法里面找不到时就会逐级往下找,在__proto__下面还有__proto__但是到这里如果没有被
// 手动更改过的话 是指向Object的,每一个对象下面__proto__下面的constructor对应的属性值就是其所在的对
// 象的构造函数),实例对象也是对象,所以实例对象也有 而且__proto__对象很特殊,它是指向了实例化其所在的对
// 象的构建函数的原型prototype的,不仅如此对象里面的__proto__对象的属性是属于其所在的对象的,而__proto__正好是指向了其所在对象的构造函数的原型prototype,而构造函数的方法恰好是写在了自己的原型prototype对象空间
// 里面,所以就得出: 实例对象去调用构造函数的方法就像是自己的方法一样,但是又没有再次申请分配地址空间,
// 重新实例化另一个对象也是这样的道理,就做到了构造函数的方法共享了。就解决了同一个构造函数实例化的对
// 象方法的地址空间不一样导致地址空间浪费的问题。妙!
Man.prototype.goHome = function () {
console.log('这里有一个' + this.age + '的男人,叫' + this.name + '身高是' + this.height + 'cm');
}
// 用构造函数实例化2个对象
var Boy = new Man('Boy', 25, 170);
var Jack = new Man('Jack', 24, 160);
console.log(Boy.goHome == Jack.goHome); // true
console.log('这个男人的信息如下:', Boy);
console.log('这个男人的信息如下:', Jack);
// 通过上面的描述,我发现了一个有意思的现象 以实例化对象Boy为例 Jack也是一样的
console.log(Boy.__proto__ == Man.prototype); // true Boy就能调用Man原型里面的方法了
// Man.prototype也是一个对象 ,那么Man.prototype.__proto__应该指向谁呢?
// 答案是对象的大哥 Object的原型prototype Object.prototype
console.log(Man.prototype.__proto__ == Object.prototype); //true Man就能调用Object原型里面的方法 了
// 问题又来了 那么 Object.prototype.__proto__又指向谁的原型呢?
// 哈哈答案是null 没有了 因为所有的 对象的大阿哥就是Object。
console.log(Object.prototype.__proto__ == null); // true 然后就没有了 , Object就只能调用自己的方法了
//不知不觉中 就形成了一个原型链,当Boy在访问一个成员的时候 在自己的属性和方法里面找不到就去自己下面的__proto__里面也就是Man.prototype里面找 ,再找不到就去Object的原型里面找,再找不到就是undefined。
// 虽然说属性和方法 ,会由对象的__proto__和该对象的构造函数的原型prototype构成原型链,但是给属性赋值的时候就不是这样了 而对象的赋值是:
// 赋值的时候,就是直接在对象自己本身赋值
// 本身上有就是修改
// 没有就是添加
// 不会和__proto__有关系
// 其实 数组也是对象 字符串也是对象 万物皆是对象 因为数组和字符串也是又构造函数(Array,String)实例化出来的 只是说字面量方式创建的数组和字符串省略了步骤而已,当被实例化出来之后 会有很多方法 比如数组.sort(),数组.pop() 这些 , 你会发现 数组下面的__proto__对象下面的constructor的值是constructor: ƒ Array() 而数组的这些方法都是Array的所以这个也相当于是一个原型链了呀 如下:
var arr = new Array(1,2,3,4,5);
arr.pop();
console.log(arr);
var str = new String('hello world');
console.log(str.slice('5')); // slice() 方法提取某个字符串的一部分,并返回一个新的字符串,且不会改动原字符串。 所以答案是 下标5到最后的元素 空格world;这其实原型链的体现啊 。所以其实原型链不难 掌握了其关键点思想 就是掌握了。
</script>
</body>
</html>
面试了前端小伙之后,我总结了他说的原型链,这次确实是我想听的!
最新推荐文章于 2024-05-03 21:05:41 发布