构造函数
//首字母是大写的函数基本都是构造函数
function Foo(name, age) {
this.name = name
this.age = age
this.class = 'class-1'
//return this //默认有这一行,就是如果不添加return this,也会默认返回this
}
var f = new Foo('zhangsan', 20)
步骤:1.传入参数 2.this变成空对象 3.return this
构造函数-扩展
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;
var arr = []; arr.a = 100;
function fn () {}; fn.a = 100;
自由扩展属性就是都可以添加a属性,自然也可以添加b,c等其他属性
2.所有的引用类型(数组、对象、函数,不包括null),都有一个proto属性,属性值是一个普通的对象
__proto__ : 隐式原型
console.log(obj.__proto__);
console.log(arr.__proto__);
console.log(fn.__proto__);
3.所有函数都有一个prototype属性,属性值也是一个普通对象
prototype: 显式原型
console.log(fn.prototype)
4.所有的引用类型(数组、对象、函数),proto属性值指向(完全等于)它的构造函数的"prototype"的属性值
console.log(obj.__proto__ === Object.prototype)
5.当试图得到一个引用类型的某个属性时,如果这个对象本身没有这个属性,那么会去它的proto(即构造函数的prototype)中寻找
//构造函数
function Foo(name, age) {
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本身没有alertName属性,那么f会去f的隐式原型中寻找,
相当于去f的构造函数Foo的prototype中寻找,Foo的显式原型已经扩展好了alertName属性
//this永远指向f自身,所以两个结果打印出的都是'zhangsan'
循环对象自身的属性
var item
for (item in f) {
//判断是否是来自f自身的属性
if (f.hasOwnProperty(item)) {
console.log(item)
}
}
原型链
f.toString() //要去f.__proto__.__proto__中寻找
instanceof
instanceof用于判断 引用类型 属于哪个 构造函数 的方法
f instanceof Foo 的判断逻辑是:
f 的 proto 一层层往上,能否对应到 Foo.prototype
再试着判断 f instanceof Object
如何准确判断一个变量是数组类型
instanceof判断
var arr = []
arr instanceof Array //true
typeof arr //object,typeof是无法判断是否是数组的
写一个原型链继承的例子
//动物
function Animal() {
this.eat = function () {
console.log('animal eat')
}
}
//狗
function Dog() {
this.bark = function() {
console.log('dog bark')
}
}
Dog.prototype = new Animal() //把Dog的显式原型赋值成一个对象
var hashiqi = new Dog()
描述new一个对象的过程
1.创建一个新对象
2.this指向这个新对象
3.执行代码,即对this赋值
4.返回this
zepto(或其他框架)源码中如何使用原型链
写一个封装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('question-header')
//console.log('div1.html()')
div1.html('<p>hello imooc</p>')
div1.on('click', function() {
alert('clicked')
})
//链式操作
//在扩展属性时,结尾返回return this,就可以有链式操作
div1.html('<p>hello imooc</p>').on('click', function() {alert('clicked')
}).html('<p>javascript</p>')