原型定义:
- 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承原型的属性和方法。原型也是对象。
- 利用原型特点和概念,可以提取共有属性。
- 对象如何查看原型 ——> 隐式属性 __proto__
- 对象如何查看对象的构造函数 —— > constructor
用下面的代码来展现下什么是原型
//Person.prototype -- 原型
//Person.prototype = {} 是祖先
Person.prototype.LastName = "haha";
Person.prototype.say = function () {console.log('abcd');
}
function Person (name, age, sex) {this.name = name;this.age = age;this.sex = sex;
}
var person1 = new Person('xuming', 35, 'male');
var person2 = new Person();
//person1和person2都可以访问祖先的LastName属性
原型是怎么来用的呢?
1-提取共有属性
//当我们每次构造一个新的对象时,下面的这些共有属性都要执行一遍,造成冗余
function Car(color, owner) {this.owner = owner;this.carName = 'BMW';this.height = 1400;this.lang = 4900;this.color = color;
}var car = new Car('red', 'prof.ji');
//修改上面的冗余 提取公共属性
Car.prototype.carName = 'BMW';
Car.prototype.lang = 4900;
Car.prototype.height = 1400;
function Car(color, owner) {this.owner = owner;this.color = color;
}var car = new Car('red', 'prof.ji');//或者用更简单的方式
Car.prototype = {carName = 'BMW',lang = 4900,height = 1400
}
function Car(color, owner) {this.owner = owner;this.color = color;
}var car = new Car('red', 'prof.ji');
2-constructor
//当我们构造这样一个对象时,会自带一个prototype属性,prototype属性里有自带两个属性,
//即
//prototype = {
// constructor:系统产生的,默认指向自己
// _proto_
//}
function Car() {
// constructor:Car
}var car = new Car();
3-隐式属性 __proto__
//当我们定义一个对象{}的时候,里面其实并不是空的
//系统已经有一个隐式的__proto__,它指向当前自己的 xxx.prototype
function Persin() {//var this = {// __proto__:Person.prototype //}
}=====================================================================================//问题1 person.name打印啥?
Person.prototype.name = 'sunny';
function Person() {// __proto__:Person.prototype
}
var person = new Person();
Person.prototype.name = 'cherry';
console.log(person.name) //打印cherry=====================================================================================//问题2 person.name打印啥?
Person.prototype.name = 'sunny';
function Person() {// __proto__:Person.prototype
}
var person = new Person();
Person.prototype = {name : 'cherry'
}console.log(person.name) //打印sunny========================================================================================
//原因:重点是这里有一个隐式的间接过程Person.prototype = {name : 'sunny'}
__proto__ = Person.prototype;
Person.prototype = {name: 'cherry'}=====================================================================================//问题3 person.name打印啥?
Person.prototype.name = 'sunny';
function Person() {// __proto__:Person.prototype
}Person.prototype = {name : 'cherry'
}var person = new Person();
console.log(person.name) //打印cherry
原型链
原型链的最顶端是Object,它就没有__proto__属性了。它的孩子都有。
Grand.prototype.lastName = "Deng";
function Grand () {}var grand = new Grand();Father.prototype = grand;
function Father() {this.name = 'xuming'
}
var father = new Father();Son.prototype = father;
function Son() {this.hobbit= 'smoke'
}
var son = new Son();
原型链增删改查
绝大多数对象的最终都会继承自Object.prototype
Object.create(原型);()里可以填两种值:原型和null
Object.create(null)创建数出来的对象是没有继承自Object.prototype的,但是Object.create(原型)创建出来的对象是有继承的
call / apply改变this指向(借用别人的函数实现自己的功能)
call() //系统默认第一个参数用以改变this指向,第二个参数开始和形参一一对应
function Person(name,age) {this.name = name;this.age = age;
}var person = new Person('deng', 100);var obj = {}Person.call(); //此时相当于Person()//但是call可以传参一个对象,如下
Person.call(obj); //此时Person里的this改变了指向,指向obj,而不是person//call() //系统默认第一个参数用以改变this指向,第二个参数才开始和形参一一对应
apply和call几乎一模一样,唯一不同的是:
call 可以传无限个参数,需要把实参按照形参的个数一个一个传进去
apply 只能传两个参数,一个改变this指向,一个封装好参数列表的数组arguments,(其实就是把一个一个的参数封装成数组传过去)