题目:
- 写一个原型链继承的例子
- 描述new一个对象的过程
- zepto(或其他框架源码中如何使用原型链)
- 如何判断一个对象是数组类型
知识基础:
1. 构造函数:用函数来初始化一个新建对象
//1.构造函数:用函数来初始化一个新建对象
//大写字母开头的函数
function Foo(name,age){
this.name = name;
this.age = age;
this.class = 'class-1';
//return this; 默认有这一行
}
var f = new Foo('beibei',22);
//乱入:语法糖:某些专门为了程序员开发方便而添加的语法
var a = {} //var a = new Object()的语法糖
var a = [] //var a = new Array()的语法糖
function Foo(){} //var Foo = new Function()的语法糖
//使用instanceof可以判断一个函数是否是一个变量的构造函数
2. 原型规则与示例
//2.原型规则与示例
//<1>所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了“null”)
var obj = {}; obj.a = 100;
var arr = []; arr.a = 100;
function fn(){}
fn.a = 100;
//<2>所有的引用类型(数组、对象、函数),都有一个__proto__属性(隐式原型),属性值是一个普通的对象
console.log(obj.__proto__);//{}
console.log(arr.__proto__);//[]
console.log(fn.__proto__);//[Function]
//<3>所有的函数,都有一个prototype属性(显式原型),属性值也是一个普通的对象
console.log(fn.prototype);//fn {}
//<4>所有的引用类型(数组、对象、函数),__proto__属性指向它的构造函数的“prototype”属性值
console.log(obj.__proto__ === Object.prototype)//true obj的构造函数就是Object
//<5>当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找
//构造函数
function Foo(name,age){
this.name = name;
}
Foo.prototype.alerName = function(){
alert(this.name)
} //此时Foo.prototype为 Object{ alerName:function,constructor: function}
//创建实例
var f = new Foo('zhangsan');
f.printName = function(){
console.log(this.name);
} //此时f为 Foo{name:'zhangsan', printName:function},
//f.__proto__ 为Object{ alerName:function,constructor: function},体现了f.__proto__ === Foo.prototype
//测试
f.printName();
f.alerName();//验证了<5>,这里的this指向f
f.toString();//要去f.__proto__.__proto___中查找
//tips:循环对象自身的属性
var item;
for(item in f){
//高级浏览器已经在for in中屏蔽了来自原型的属性
//但是这里建议大家还是加上这个判断,保证程序的健壮性
if(f.hasOwnProperty(item)){
console.log(item);//name printName 没有alertName
};
};
4. instanceof:用于判断引用类型属于哪个构造函数的方法
f instanceof Foo的判断逻辑是:
- f的__proto__一层一层往上,能否对应到Foo.prototype
- 再试着判断 f instanceof Object
问题解答:
5. 如何判断一个对象是数组类型
//如何判断一个变量是数组类型
var arr = [];
arr instanceof Array //ture
typeof arr //object,typeof是无法判断是否是数组的
6. 原型链继承的例子
//理解例子
function Animal(){
this.eat = function(){
console.log('animal eat');
}
}
function Dog(){
this.bark = function(){
console.log('dog bark')
}
}
Dog.prototype = new Animal()
var hashiqi = new Dog()
//封装一个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
//innerHTML在js是双向功能:获取对象内容 或 像对象插入内容
}
}
Ele.prototype.on = function(type,fn){
var elem = this.elem;
elem.addEventListener(type,fn)
}
var div1 = new Elem('div1')
console.log(div1.html()) //这时val是空 会返回原来页面的内容
div1.html('<p>holle</p>').on('click',function(){
alert('clicked')
}).html('<p>javascript</p>') //可以链式操作
7. 描述new一个对象的过程
- 创建一个新对象
- this指向这个对象
- 执行代码,即对this赋值
- 返回this
8. zepto(或其他框架源码中如何使用原型链)
- 阅读源码是高效提高技能的方式
- 但不能“埋头苦钻“有技巧在其中
- 慕课网搜索”zepto设计与源码分析“