原型和原型链

对于js中原型的理解,我仅处在初级阶段。我的理解是,js的原型是为了实现“类”的概念,可以使得对象的方法可以通用,实现类的继承。虽然js中并没有类的概念,但是多数情况下,人们还是偏向于使用面向对象的概念在编程。

Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。当我们用js来模拟类时就涉及到了原型链的概念。原型链和作用域链的作用很相似,都是用来定义查询变量的一种规则。当你在自身查找不到某个变量或者方法的时候,原型链会根据规则继续向上查找,直到顶端为止。

比如,在定义一个“类”的时候,通常会先定义一个构造函数,里面包含了实例属性。

function Person (name, age) {
     this.name = name;
     this.age = age;
}

他可能包含了一些通用的方法(类方法),比如读取姓名和年龄,安排班级等

Person.prototype.getName = function () {
    return this.name;
}
Person.prototype.getAge = function () {
    return this.age;
}

当我们需要给一个类定义通用的方法的时候,我们需要在它的原型上定义属性,这样,所有通过构造函数生成的实例都可以调用该方法。

继承的实现也是因为有原型的存在得以实现,通用的实现继承方法如下:

 
function Person (name, age) {
     this.name = name;
     this.age = age;
}
Person.prototype.getName = function () {
    return this.name;
}
Person.prototype.getAge = function () {
    return this.age;
}
Person.prototype.setAge = function (age) {
    this.age = age;
}
function Teacher(name,age,no){
    //实现子类属性的继承,每个实例都有属于自己的属性,同时需要注意参数的顺序,call函数只看重顺序,不在乎参数名称     
    Person.call(this, name, age);     
    this.classNo = no;
}
Teacher.prototype = new Person();  //将父类的对象赋值给子类,原型对象,这样子类就继承了父类的方法

// 在支持ES5的浏览器推荐下面的写法:(创建一个新的对象,内容是Person.prototype,将其赋值给Teacher.prototype,这样就将Person的原型和Teacher的原型相关联,并不会产生副作用)// Teacher.prototype = Object.new(Person.prototype);

Teacher.prototype.getInfo = function () {
       console.log('name:' + this.name + 'age:' + this.age + 'classNo:' + this.classNo);
}
var teacherLi = new Teacher('Li', 30, 2);
teacherLi.getInfo(); //name:Liage:30classNo:2
teacherLi.setAge(28);
teacherLi.getInfo(); //name:Liage:28classNo:2

一. new操作符的含义

当我们使用new操作符时,实际上就是创建一个对象。但在实际运行当中,new是创建了两个对象,并将其相互关联。例如上面的例子中var teacherLi = new Teacher('Li', 30, 2); 这句话,new操作符创建了一个对象并将它赋值给teacherLi,并将teacherLi和Teacher.prototype相联系,teacherLi.__proto__ === Teacher.prototype。

在ES5规范里,针对new的操作的定义如下:

image

简单理解就是:

1. 新建一个对象

2. 将对象的内部__proto__属性和构造函数的prototype相关联

3. 利用构造函数给实例对象属性赋值

4. 如果构造函数没有显示返回对象,则返回步骤一创建的对象

二.constructor

Foo.prototype.constructor === Foo

Foo.prototype的.constructor属性只是Foo函数在声明时的默认属性。如果prototype被重新赋值声明,那么constructor就不知道是指向谁了,它会根据原型链一直检索,直到检索到最上层Object对象。

function Foo() { /* .. */ }
Foo.prototype = { /* .. */ }; // 创建一个新原型对象
var a1 = new Foo();
a1.constructor === Foo; // false!
a1.constructor === Object; // true!

三.prototype&__proto__

对象的__proto__属性指向它关联的prototype对象。可以简单的理解为实例的__proto__属性指向它的原型对象。

function Foo(a) {
    this.a = a;
}
var foo = new Foo('foo');
console.log(foo.__proto__ === Foo.prototype);
console.log(Foo.__proto__ === Function.prototype);
console.log(Function.__proto__ === Function.prototype);
console.log(Function.prototype.__proto__ === Object.prototype);
console.log(Object.prototype.__proto__ === null);

以上的答案都是true,可以看到当你用new标识符来创建一个属性时它会默认应用建立原型链,一直关联到Object这个对象原型。

在js的内置类型当中:

Number.__proto__ === Function.prototype  // true
Boolean.__proto__ === Function.prototype // true
String.__proto__ === Function.prototype  // true
Object.__proto__ === Function.prototype  // true
Function.__proto__ === Function.prototype // true
Array.__proto__ === Function.prototype   // true
RegExp.__proto__ === Function.prototype  // true
Error.__proto__ === Function.prototype   // true
Date.__proto__ === Function.prototype    // true
Math.__proto__ === Object.prototype  // true
JSON.__proto__ === Object.prototype // true

因为Function.prototype.__proto__ === Object.prototype得值是true,所以,函数也是对象。

之前看到过一套测试题,放在这里以供思考:

function Foo() {
    getName = function () { alert (1); };
    return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}
 
//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();

解释地址:http://web.jobbole.com/85122/

转载于:https://www.cnblogs.com/Candybunny/p/5476244.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值