原型 原型链 call / apply

原型定义:

  1. 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承原型的属性和方法。原型也是对象。
  2. 利用原型特点和概念,可以提取共有属性。
  3. 对象如何查看原型  ——> 隐式属性 __proto__
  4. 对象如何查看对象的构造函数 —— > 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,(其实就是把一个一个的参数封装成数组传过去)

发布了65 篇原创文章 · 获赞 11 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/u011280778/article/details/96979279