JS基础(二)原型与原型链

一、构造函数

概念:类似于模板引用的机制

  • new一个构造函数,返回对象的过程
//注意函数的首字母大写
function Foo(name,age){   //传入2个参数
  this.name = name    	  //对name进行赋值
  this.age = age          //对age进行赋值
  this.class = 'class-1'  
  // return this     // 默认有这一行
}
var f = new Foo('zhangsan',18)

//通过Foo这个构造函数可以new出很多个不同的实例
// eg: var f1 = new Foo('lidi',19)

定义 f 赋值为 new,new 是一个构造函数形成实例的过程;然后把字符串 'zhangsan'、数字 20 传进去。

  • new一个对象的过程
    ① new 的时候把参数传进去(也可以不传);
    ② new 之前,函数里面的 this 会先变成一个空对象;
    ③ 然后进行属性的赋值(例如:this.name=name);
    ④ 赋值完之后,再默认把 thisreturn 回来;
    ⑤ return 回来之后赋值给 f ,此时,f 具备了属性
f.name=zhangsan;  
f.age=18;  
f.class = class-1  
  • 简述new一个对象的过程
    ① 创建一个新对象
    ② this 指向这个新对象
    ③ 执行代码,即对 this 赋值
    ④ 返回 this

  • this
    通过对象的属性的形式来执行函数时,无论是函数自身的属性还是函数原型中得到的属性,函数中的this永远指向对象f自身

  • 扩展
    var a={}var a = new Object() 的语法糖 (推荐前者写法)
    var a=[]var a = new Array( ) 的语法糖(推荐前者写法)
    function Foo( ){…}var Foo = new Function(…) 的语法糖(推荐前者写法)

  • instanceof 用于判断引用类型属于哪个构造函数的方法

  • instanceof Array 判断一个变量是否为数组

二、原型规则

  1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了null以外)
var obj = { }; obj.a = 100;   // 定义了一个对象,对象扩展属性a
var arr = { }; arr.a = 100;  // 定义了一个数组,数组扩展属性a
function fn ( ){ }  // 定义了一个函数
fn.a = 100;   // 给函数增加属性值
  1. 所有的引用类型(数组、对象、函数),都有一个__proto__【隐式原型】属性,属性值是一个普通对象
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
  1. 所有的函数,都有一个 prototype 属性【显式原型】,属性值也是一个普通对象
console.log(fn.prototype)
  1. 所有的引用类型(数组、对象、函数),__proto__属性值指向它的构造函数的 prototype 属性值
console.log(obj.__proto__ === Object.prototype)
  1. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么它会去它的 __proto__ (即它的构造函数的 prototype )中寻找。【 由于对象的隐式原型 === 它构造函数的显式原型 】
// 定义一个构造函数
function Foo(name,age){
	this.name = name
}
Foo.prototype.alertName = function(){
	alert(this.name)   //this就是f
}
// 创建实例
var f = new Foo('zhangsan')
f.printName = function(){
	console.log(this.name)
}
// 测试
f.printName( )  // 通过对象的属性的形式来执行函数时,无论是函数自身的属性还是函数原型中得到的属性,函数中的this永远指向对象f自身
f.alertName( )
  1. 扩展
    this
    通过对象的属性的形式来执行函数时,无论是函数自身的属性还是函数原型中得到的属性,函数中的 this 永远指向对象 f 自身
    循环对象自身的属性
var item
for(item in f){
  // 高级浏览器已经在for in中屏蔽了来自原型的属性
  //但是这里建议加上这个判断,保证程序 的兼容性。
  if( f.hasOwnProperty(item) ){
    console.log(item)
  }
  /* 通过hasOwnProperty判断,如果通过,则是对象自身的属性;否则是来自原型中的属性 */
}

API: hasOwnProperty :判断对象自身属性、兼容性

三、原型链

例子:toString()

// 构造函数
function Foo( ){
  this.name = name
}
Foo.prototype.alertName = function( ){
  alert(this.name)
}
// 创建示例
var f = new Foo('zhangsan')
f.printName = function( ){
  console.log(this.name)
}
// 测试
f.printName( )
f.alertName( )
f.toString( )   // 要去f.__proto__.__proto__中查找

理解:根据第 5 条原型规则来看:

  • toStringf 自身没有 toString 这个属性,要去f自身的隐式原型中找;相当于要去其构造函数的显式原型中找,即Foo.prototype
  • Foo.prototype 没有这个 toString 属性,同时,Foo.prototype 属性值也是一个对象【规则3】,那么可以去 Foo.prototype 这个属性值【对象】的隐式原型中找;因为【对象】的隐式原型也就等于构造函数 Object 的显式原型,即 Foo.prototype.__proto__ ===Object.prototype
  • 此时,Object.prototype 的原型是 nullnull 没有任何属性和方法,也没有自己的原型;因此原型链的尽头就是 null
    Object 是有 toString属性的。

四、面试题

  1. 如何准确判断一个变量是数组类型
var arr = [ ]
arr instanceof Array     // true
typeof arr  // object,  typeof是无法判断是否是数组的  
  1. 写一个原型链继承的例子(必须掌握)
    实战:可写一个封装DOM查询的例子
小例子:(不要在面试中写)
// 动物
function Animal(){  //定义一个构造函数Animal
  this.eat = function(){  //定义一个eat属性
    console.log('animal eat')
  }
}
//狗
function Dog(){  //定义一个构造函数Dog
  this.bark = function(){
    console.log('dog bark')
  }
}
Dog.prototype = new Animal()  //构造函数Dog的显式原型已经有一个对象,把这个对象改掉,赋值成new Animal(); new Animal()返回出来是一个Animal new出来的一个对象,具有eat属性。
//即:把Dog这个显式原型,赋值成一个对象,这个对象有一个eat属性,

//哈士奇
var hashiqi = Dog()
  1. 描述 new 一个对象的过程(要知道原理)
    ① 创建一个新对象
    ② this 指向这个新对象
    ③ 执行代码,即对 this 赋值
    ④ 返回 this
  2. zepto(或其他框架)源码中如何使用原型链(源码实现)
    阅读源码是高效提高技能的方式,有技巧地读(先在网上找资料如何去读)
    eg: 搜索 “jquery源码解读分析” ,先有铺垫,是什么样的结构;带着这些信息来读
    eg: 慕课网搜索 " zepto 设计和源码分析 "
    zepto、jquery、anderstoer 源码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Windyluna

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值