js 面向对象

113 阅读3分钟
构造函数(constructor)——对象的模板
  • 函数体内部使用了this关键字,代表了所要生成的对象实例。
  • 生成对象的时候,必须使用new命令,过程如下。
    • 创建一个空对象,作为将要返回的对象实例。
    • 将这个空对象的原型,指向构造函数的prototype属性。
    • 将这个空对象赋值给函数内部的this关键字。
    • 开始执行构造函数内部的代码。
原型对象(prototype)

JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。

function P() {};
typeof P.prototype; // "object"

prototype => {constructor:P}

P.prototype.constructor === P; // true

修改原型对象时(比如继承和已有对象生成实例),一般要同时修改constructor属性的指向

var MyArray = function () {};

MyArray.prototype = new Array();
MyArray.prototype.constructor = MyArray;

获取实例对象obj的原型对象

obj.__proto__ // __proto__属性只有浏览器才需要部署
obj.constructor.prototype 
Object.getPrototypeOf(obj)
继承
// 第一步是在子类的构造函数中,调用父类的构造函数。
function Sub(value) {
  Super.call(this);
  this.prop = value;
}
// 第二步,是让子类的原型指向父类的原型,这样子类就可以继承父类原型。
Sub.prototype = Object.create(Super.prototype); // new Super()
Sub.prototype.constructor = Sub;
Sub.prototype.method = '...';

多重继承 (这种模式又称为 Mixin(混入))

function M1() {
  this.hello = 'hello';
}

function M2() {
  this.world = 'world';
}

function S() {
  M1.call(this);
  M2.call(this);
}

// 继承 M1
S.prototype = Object.create(M1.prototype);
// 继承链上加入 M2
Object.assign(S.prototype, M2.prototype);

// 指定构造函数
S.prototype.constructor = S;

var s = new S();
s.hello // 'hello'
s.world // 'world'
方法区分
  1. 原形对象方法 prototype.func
  2. 静态方法 构造函数上的方法 Constructor.func
  3. 实例方法 this.func
object 静态方法
  • Object.create()

以这个现有的对象作为模板,生成新的实例对象,这时就可以使用Object.create()方法。

Object.create()方法的实质:

if (typeof Object.create !== 'function') {
  Object.create = function (obj) {
    function F() {}  // 1. 新建一个空的构造函数F
    F.prototype = obj; // 2. 让`F.prototype`属性指向参数对象obj
    return new F(); // 3. 返回一个F的实例
  };
}

所以Object.create()方法生成的新对象,动态继承了原型。在原型上添加或修改任何方法,会立刻反映在新对象之上。

var obj1 = { p: 1 };
var obj2 = Object.create(obj1);

obj1.p = 2;
obj2.p // 2

三种方式生成的新对象是等价

var obj1 = Object.create({});
var obj2 = Object.create(Object.prototype);
var obj3 = new Object();

对象的拷贝

  • 确保拷贝后的对象,与原对象具有同样的原型。
  • 确保拷贝后的对象,与原对象具有同样的实例属性。
function copyObject(orig) {
  return Object.create(
    Object.getPrototypeOf(orig),
    Object.getOwnPropertyDescriptors(orig)
  );
}
  • Object.prototype.hasOwnProperty()

判断某个属性定义在对象自身,还是定义在原型链上。

this
  1. 构造函数中表示实例对象;

  2. 全局环境表示windows对象

  3. 对象方法this指向当前一层的对象,赋值给另个对象会改变this指向,一般会出现如下

    1. 嵌套
    // 属性嵌套
    var a = {
      b: {
        m: function() {
          console.log(this.p);
        },
        p: 'Hello',
      }
    };
    
    (a.b).m() // 等同于 b.m()
    
    // 方法嵌套
    var o = {
      f1: function () {
        console.log(this);
        var f2 = function () {
          console.log(this);
        }();
      }
    }
    
    o.f1()
    // Object
    // Window
    
    1. 回调函数 (回调函数中的this往往会改变指向,最好避免使用)
    var o = new Object();
    o.f = function () {
      console.log(this === o);
    }
    
    // jQuery 的写法
    $('#button').on('click', o.f);
    // f方法是在按钮对象的环境中被调用的
    
this绑定

bind()方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。

apply()方法改变this指向,然后接收一个数组作为函数执行时的参数再调用该函数

call()方法指定函数内部this的指向(即函数执行时所在的作用域),接收func.call(thisValue, arg1, arg2, ...),调用该函数。

引用

wangdoc.com/javascript/…