第二部分 原型和原型链
对应知识点
1、构造函数
构造函数名字首字母大写
执行过程:
先执行new new 执行之后 this变成空对象 再去调Foo函数 最后赋值给f f就变成一个函数对象
function Foo(name, age){
// this.xxx = xxx 属性的赋值
this.name = name;
this.age = age;
this.class = 'class - 1'
// return this; // 默认有这一行
}
// 先执行new new 执行之后 this变成空对象 再去调Foo函数 最后赋值给f f就变成一个函数对象
var f = new Foo('zhanan',18)
// var f1 = new Foo('zhanan',18) // 可以创建多个对象
2、构造函数 - 扩展
(1)var a = {} 其实是 var a = new Object()的语法糖
(2)var a = [] 其实是 var a = new Array()的语法糖
(3)function Foo(){...} 其实是var Foo = new Function(..)
(4)使用instanceof 判断一个函数是否是某个变量的构造函数,如判断一个变量是否为数组 变量 instanceof Array
3、原型规则和示例
(1) 所有的引用类型(数组、对象、函数),都具有对象特性,即可以自由扩展属性(null除外)
(2)所有的引用类型(数组、对象、函数),都有一个 proto (隐式原型)属性,属性值是一个普通对象
(3)所有的函数,都有一个 prototype (显示原型)属性,属性值也是一个普通的对象。
(4) 所有的引用类型(数组、对象、函数)。__proto__属性值指向他的构造函数的 prototype 属性值
即有
var obj = {...};
obj.a = 100;
// 有
obj.__proto__ === Object.prototype;
(5)当试图得到一个对象(引用类型)的某个属性时,如果这个对象本身没有这个属性,那么会去它的 proto (即它的构造函数的prototype)中寻找。
(6)hasOwnProperty ----- 只获取引用类型本身的属性
// f 是一个对象
var items;
for(item in f){
// 高级浏览器已经在for in 中屏蔽了来自原型的属性
// 建议获取自身属性时加上 hasOwnProperty()判断
if(f.hasOwnProperty(item)){
....
}}
4、原型链
// 构造函数
function Foo(name,age){
this.name = name
}
Foo.prototupe.alertName = function(){
alert(this.name)
}
//创建实例
var f = new Foo('zhnasan')
f.printName = function() {
console.log(this.name)
}
//测试
f.printName()
f.alertName()
f.toString() // 要去f.__proto__.proto 中查找
f.proto 指向 Foo.prototype,Foo.proto 指向Object.prototype,__proto__顺着原型链往下查找,找到最后Object.proto=== null 的时候表示已经到尽头了
5、instanceof
用于判断 引用类型属于哪个构造函数的方法
var a = { }
console.log(a instanceof Object) // true
对应面试题
1、如何准确判断一个变量数组类型
使用instanceof判断
var a = [];
console.log(a instanceof Object) // true
// 不能用typeof 来判断,typeof 判断基本数据类型
2、写一个原型链继承的例子
封装一个DOM查询的例子
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('div')
// 获取dom节点内容
console.log(div1.html())
// 改变内容
div1.html('<p> hello <p>')
// 绑定事件
div1.on('click',function(){
alert('cliked')
// 链式操作
div1.html('<p> hello <p>').on('click',function(){
alert('cliked')
}).html('<p>javascript</p>')
3、描述 new 一个对象的过程
描述:
(1)创建一个新对象
(2)this 指向这个新对象
(3)执行代码,即对 this 赋值
—> 执行过程:先执行new new 执行之后 this变成空对象 再去调Foo函数 最后赋值给 f f 就变成一个函数对象
(4)返回 this
function Foo(name, age){
// this.xxx = xxx 属性的赋值
this.name = name;
this.age = age;
this.class = 'class - 1'
// return this; // 默认有这一行
}
// 先执行new new 执行之后 this变成空对象 再去调Foo函数 最后赋值给f f就变成一个函数对象
var f = new Foo('zhanan',18)
// var f1 = new Foo('zhanan',18) // 可以创建多个对象
4、如何理解原型?如何理解原型链?
原型是一个对象,对象的__proto__(隐式原型) 属性指向原型,proto 将对象和原型连接起来组成了原型链。
原型
(1)每个函数都有一个prototype·属性,被称为显式原型属性
(2)每个实例对象都有__proto__属性,被称为隐式原型属性
(3)每个实例对象的隐式原型属性__proto__都指向自身构造函数的显式原型属性,即有 obj.proto === Object.prototype。
(4)每个显式原型都有一个constructor(构造函数)属性,指向它关联的构造函数
原型链
获取对象属性时,如果对象本身没有这个属性,就会通过__proto__到它的原型上找,如果找不到,就会继续往原型的原型找,直到找到最顶层Object.prototype,在这个过程中对象的__proto__(隐式原型) 属性指向原型,proto 将对象和原型连接起来组成了原型链,Object.prototype的__proto__属性值为 null 时表示找到了顶层了。