- 定义
原型是function对象的一个属性,它定义了构造函数制造出来的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
- 利用原型特点和概念,可以提取共有属性。
- 对象如何查看原型 --> 隐式属性 __proto__
- 对象如何查看对象的构造函数 --> constructor
//Person.prototype --> 原型
//Person.prototype = {} 是祖先
Person.prototype.name = 'xiaoming'
function Person() {
// constructor: Person // 默认 可修改
}
var person = new Person();
person.name; // 'xiaoming'
var person1 = new Person();
person1.name; // 'xiaoming'
person.constructor; // 输出 Person(){}
// constructor 可设置构造对象的构造器 可用来找爹
function Car() {}
Car.prototype = {
constructor: Car
}
function Car2() {}
var car = new Car2();
car.constructor; // 输出 function Car(){} // car来自 function Car(){}
// __proto__ 存的是该对象的原型
Person3.prototype.name = 'abc';
function Person3() {
// var this = {
// __proto__: Person3.prototype
// }
}
var obj = {
name: 'sunny'
}
var person3 = new Person3();
person3.name; // 输出 'abc'
person3.__proto__ = obj;
person3.name; // 输出 'sunny'
- 原型练习
Person.prototype.name = 'sunny';
function Person() {
}
person.prototype.name = 'cherry';
var person = new Person();
// person.prototype.name = 'cherry'; // 写在new的后面也一样打印出cherry 因为改的是属性
console.log(person.name); // 'cherry';
Person2.prototype.name = 'sunny';
function Person2() { }
Person2.prototype = {
name: 'cherry'
}
var person2 = new Person2();
// Person2.prototype = { // 如果在new的后面改prototype 无效,对象已经new出来了
// name: 'apple'
// }
console.log(person2.name); // 'cherry' 执行顺序,new的时候 prototype 已经被改变
- 原型链
绝大多数对象的最终都会继承自Object.prototype
Object.create(原型)
- 原型链练习
// 原型链的链接就是 __proto__
// 原型链的终端就是Object.prototype
// Grand.prototype.__proto__ ==> Object.prototype
Grand.prototype.lastName = 'wang';
function Grand() {}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'xiaoming',
this.fortune = {
card1: 'visa'
},
this.num = 100
}
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'smoke'
}
var son = new Son();
console.log(son.hobbit); // 'smoke'
console.log(son.name); // 'xiaoming'
console.log(son.lastName); // 'wang'
son.fortune.card2 = 'master'; // 操作的是父级的fortune
console.log(father.fortune); // { card1: 'visa', card2: 'master'}
son.num ++; // son.num = son.num + 1; // son.num => 101; 未改变父级的num
console.log(father.num); // 100;
console.log(son.num); // 101;
- 练习2
Person.prototype = {
name: 'a',
sayName: function () {
console.log(this.name);
},
height = 100;
}
function Person() {
this.name = 'b';
this.eat = function () {
this.height ++;
}
}
var person = new Person();
console.log(person.sayName()); // 输出 ‘b’ 因为是Person调用的
console.log(person.prototype.sayName()); // 输出 ‘a’
person.eat();
console.log(person.height); // 101
console.log(person.height); // 100
- Object.create(原型 / null)
var obj = Object.create(null);
console.log(obj.prototype); // 空的,因为null 没有prototype
// 即使手动给他赋值 prototype 也无法继承 因为不是系统自动生成的
Person.prototype = {
name: 'a'
}
function Person() { }
var person = new Person();
// 以上代码可以写成 var person = Object.create({name: 'a'});
- 拓展 toString()
// 123.toString(); // 报错,因为这个点会被系统识别为小数点
// 正确要写成
var num = 123;
num.toString();
// 数字 toString() 会调用包装类 new Number(num)
// Number 有toString方法 重写了 Object.toString
// Number.prototype.toString = function() {}
// Number.prototype.__proto__ ==> Object()
// 重写了 Object.toString()
// Array.prototype.toString
// Booblean.prototype.toString
// String.prototype.toString
// 我们可以根据情况重写toString方法
Number.prototype.toString = function() {
return 321;
}
var num1 = 123;
num1.toString(); // 输出321
- 拓展 JavaScript精度计算
可正常计算的范围 小数点前16位和后16位
var num = 0.14;
console.log(num * 100); // 输出 14.000000000000002