5条原型规则

  1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了"null")以外
  2. 所有的引用类型(数组、对象、函数),都有一个__proto__ (隐式原型)属性,属性值是一个普通的对象
  3. 所有的函数,都有一个 prototype (显式原型)属性,属性值也是一个普通的对象
  4. 所有的引用类型(数组、对象、函数),__proto__ 属性值指向它的构造函数的 prototype 属性值
  5. 当试图得到一个对象(引用类型)的某个属性时,如果这个对象本身没有这个属性,那么会去它的 __proto__(即它的构造函数的 prototype)中寻找
var obj = {};
obj.a = 100;
var arr = [];
arr.a = 100;
function fn () {}
fn.a = 100;

console.log(obj.__proto__); // Object
console.log(arr.__proto__); // Array
console.log(fn.__proto__); // ƒ () { [native code] }

console.log(fn.prototype); // Object

console.log(obj.__proto__ === Object.prototype); // true

如何准确判断一个变量是数组类型?

var arr = [];
arr instanceof Array // true
typeof arr // object typeof无法判断是否是数组

一个原型链继承的例子

function Elem(id) {
    this.elem = document.getElementById(id);
}

Elem.prototype.html = function (val) {
    var elem = this.elem;
    if (val) {
        elem.innerHTML = val;
        return this; // 链式调用
    } else {
        return elem.innerHTML;
    }
};

Elem.prototype.on = function (type, fn) {
    var elem = this.elem;
    elem.addEventListener(type, fn);
    return this;
};
var div1 = new Elem('articleTitle');

console.log(div1.html());
div1.html('<p>hello gril~</p>');
div1.on('click', function () {
    alert('clicked!');
});

div1.html('<p>hello gril~</p>').on('click', function () {
    alert('clicked!');
}).html('<p>Nice to meet you.</p>');

描述 new 一个对象的过程

创建一个新对象
this指向这个新对象
执行代码,即对this赋值
返回this
function Foo (name, age) {
    // 首先this变成空对象
    this.name = name;
    this.age = age;
    this.class = 'class-1';
    // return this; // 默认有这一行
}
var f = new Foo('li', 20);
var f1 = new Foo('wang', 22); // 创建多个对象

构造函数

function Foo (name, age) {
    this.name = name;
}
Foo.prototype.getName = function () {
    console.log(this.name);
};
// 创建实例
var f = new Foo('can');
f.printName = function () {
    console.log(this.name);
};
// 测试
f.printName();
f.getName();
f.toString(); // 要去 f.__proto__.__proto__ 中查找
for (var key in f) {
    // 我们希望循环得到的是对象本身的属性,而不希望得到来自原型的属性
    // 高级浏览器已经在 for in 中屏蔽了来自原型的属性
    // 但是建议还是加上这个判断,保证程序的健壮性
    if (f.hasOwnProperty(key)) {
        console.log(key); // name printName
    }
}

instanceof 用于判断引用类型属于哪个构造函数的方法
f instanceof Foo 的判断逻辑是:f 的__proto__ 一层一层往上,是否对应到Foo.prototype,再试着判断 f instanceof Object

原型链


lxcan
337 声望32 粉丝