面试题(2)之 原型

写在前面

我们知道所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的,要记住,所有的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.prototype。这也正是所有自定义类型都会继承toString()、valueOf()等默认方法的根本原因。

实例一

  var Fn = function() {}; 

  Object.prototype.a = function() {};
  Function.prototype.b = function() {};

  var f = new Fn(); 
  /*打印实例对象f的a属性,由原型链知,
  f.__proto__.__proto__==Object.prototype,
  而a是Object.prototype的自定义类型,所以
  f中也有a属性。*/
  console.log(f.a) // ƒ () {}
  /* b为Function()构造器原型Function.prototype的
  自定义属性,而a是Object.prototype的自定义类
  型,Function.prototype.__proto__==Object.prototype,
  所以没有联系,返回undefined
  */
  console.log(f.b) // undefined
  /*构造函数Fn()是Function()的实例对象,
  所以Fn.__proto__==Function.prototype,
  b为Function()构造器原型Function.prototype
  的自定义属性*/
  console.log(Fn.b) // ƒ () {}
  /*Fn.__proto__.__proto__==Function.prototype,*/
  console.log(Fn.a) // ƒ () {}

实例二

  function  foo() {   
      foo.a = function() {
          alert(1)
      };     
      this.a = function() {
          alert(2)
      };    
      a = function() {
          alert(3)
      };    
      var  a  =   function() {
          alert(4)
      };
  }; 
  foo.prototype.a = function() {
      alert(5)
  };
  foo.a = function() {
      alert(6)
  };
  // 直接调用foo.a()函数,因为foo()没有调用,所以执行输出6
  foo.a();  // 6
  // 调用foo()
  var obj = new foo();
  //this==>obj
  obj.a();  // 2
  // 调用完foo()后,alert(1)会把alert(6)覆盖
  foo.a();  // 1

实例三

    var obj = {
      proto: {
        a: 1,
        b: 2
      }
    };
    function F() { };
    F.prototype = obj.proto;
    var f = new F();
    obj.proto.c = 3;
    obj.proto = {
      a: -1,
      b: -2
    };
    alert(f.a);   // 1
    alert(f.c);   // 3
    delete F.prototype['a'];
    alert(f.a);  // undefined
    alert(obj.proto.a);  // -1

分析:首先定义一个obj对象,其值为一个proto对象,后来定义一个F()的函数,,这时候obj和F()的原型指向同一个地址,然后给obj.proto增加一个c=3;所以obj改变了自然而然F()也改变的,F()中也存在c,后来obj把proto重新赋值一个新的对象,就是把obj的proto指向一个新的地址,但是修改后对F()的所有都不影响。

实例四

// 创建一个Foo函数  
function Foo() {
      getName = function() {
          alert(1);
      }
      return this;
  }
// 给Foo函数添加一个函数属性getName
  Foo.getName = function() {
      alert(2);
  }
  // 在Foo的原型上添加一个getName函数属性
  Foo.prototype.getName = function() {
      alert(3);
  }
  // 以函数表达式的方式创建一个getName函数
  var getName = function() {
      alert(4);
  }
  // 以函数声明的方式创建一个getName函数
  function getName() {
      alert(5);
  }
 // 调用Foo.getName函数
  Foo.getName(); //2
 // 调用getName函数,预解析使得 “以函数声明的方式创建一个getName函数” 提前,然后 “以函数表达式的方式创建一个getName函数” 覆盖,输出为 4
  getName(); // 4
 // 调用 Foo函数,然后再调用其中的getName函数
  Foo().getName(); // 1 
 // 调用 Foo函数后,getName有被覆盖掉,Foo中的getName由局部变成全局
  getName(); // 1
 // 创建 Foo.getName() 的实例
  new Foo.getName() // 2
 // 调用Foo(),返回this,指向window,然后调用window的getName
  new Foo().getName(); //3
 //  理解 new this.getName this 指向 window
  new new Foo().getName(); //3

 

转载于:https://www.cnblogs.com/houfee/p/9131370.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
原型链是JavaScript中非常重要的一个概念,它是实现继承的主要方法之一。在JavaScript中,每个对象都有一个原型对象,而原型对象也可以有自己的原型对象,这样就形成了一个原型链。当我们访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,就会去它的原型对象中查找,如果还没有,就会去原型对象的原型对象中查找,直到找到该属性或方法或者到达原型链的顶端为止。 下面是一个简单的例子,演示了原型链的基本概念: ```javascript function Person(name, age) { this.name = name; this.age = age; } Person.prototype.sayHello = function() { console.log("Hello, my name is " + this.name); }; function Student(name, age, grade) { Person.call(this, name, age); this.grade = grade; } Student.prototype = Object.create(Person.prototype); Student.prototype.constructor = Student; Student.prototype.sayGrade = function() { console.log("My grade is " + this.grade); }; var student = new Student("Tom", 18, 3); student.sayHello(); // 输出:Hello, my name is Tom student.sayGrade(); // 输出:My grade is 3 ``` 在上面的例子中,我们定义了一个`Person`构造函数和一个`Student`构造函数,`Student`构造函数继承自`Person`构造函数。我们通过`Object.create`方法将`Student`的原型对象指向`Person`的原型对象,这样就形成了一个原型链。当我们调用`student.sayHello()`方法时,由于`student`对象本身没有`sayHello`方法,就会去它的原型对象`Person.prototype`中查找,找到了该方法并执行。当我们调用`student.sayGrade()`方法时,由于`student`对象本身没有`sayGrade`方法,就会去它的原型对象`Student.prototype`中查找,找到了该方法并执行。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值