原型和原型链
问题:
-
如何准确判断一个变量是数组类型
-
写一个原型链继承的例子
-
描述new 一个对象的过程
-
Zepto(或其他框架)源码中如何使用原型链
知识点:
1.构造函数
function Foo (name, age) {
this.name = name;
this.age = age;
this.class = 'class-1';
}
Foo
/* ƒ Foo (name, age) {
this.name = name;
this.age = age;
this.class = 'class-1';
} */
var f = new Foo('xiaoming', 12)
f
//Foo {name: "xiaoming", age: 12, class: "class-1"}
建议构造函数的首字母用大写便于阅读。
构造函数会默认return this.
这里讲一下“var f = new Foo('xiaoming', 12)”也就是new一个对象的过程:
首先先传入相应的参数在这个构造函数,然后其实先有一个this,为空对象,再将其进行赋值。像我们前一次讲到的对象是属于引用类型,引用类型可以无限的扩展属性,这里this.name,this.age都可以有点像那个无限扩展属性,给他加上属性,然后赋值,然后最后再返回一个return this。再将这个this传回来,赋值给f.
2.构造函数--扩展
语法糖:
语法糖就是一种便捷写法。在达到相同的目的情况下,更简便的方法。
- var a ={} 其实是var a = new Object() 的语法糖
- var a = [] 其实是var a = new Array()的语法糖
- function Foo(){...} 其实是var Foo =new Function(..)
- 使用instanceof 判断一个函数是否是一个变量的构造函数
对于一个变量的所有东西都有构造函数,对象,函数,数组都是有构造函数的.
对于1,2,3都推荐前者,易读且性能更好
//构造函数拓展
var a = {}
var b = []
function fn (){}
var a = new Object
var b = new Array
fn = new Function (...)
3.原型规则和示例
5条原型规则
原型规则是学习原型链的基础
(1)所有的引用类型(数组,对象,函数),都可以可自由扩展属性(除了null除外)
(2)所有的引用类型(数组,对象,函数),都有一个_proto_属性(简称他隐式原型),属性值是一个普通的对象。
(3)所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通的对象
(4)所有的引用类型(数组,对象,函数),_proto_属性值指向它的构造函数”prototype ”的属性值
(5) 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的_proto_(即它的构造函数的prototype)中寻找。
var obj = {}
obj.a = 100
obj.b = 'abc'
obj
//{a: 100, b: "abc"}
var arr = [1,2,3]
arr.a = 100
arr
//(3) [1, 2, 3, a: 100]
function fn () {}
fn.a = 100
fn.b =200
obj
//{a: 100, b: "abc"}
arr
//(3) [1, 2, 3, a: 100]
fn
//ƒ fn () {}
obj.__proto__
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
arr.__proto__
//[constructor: ƒ, concat: ƒ, find: ƒ, findIndex: ƒ, pop: ƒ, …]
fn.__proto__
//ƒ () { [native code] }
fn
//ƒ fn () {}
Object
//ƒ Object() { [native code] }
fn.prototype
//{constructor: ƒ}
Object.prototype
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
obj
//{a: 100, b: "abc"}
obj.__proto__
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
Object
//ƒ Object() { [native code] }
Object.prototype
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
obj.__proto__ === Object.prototype
//true
4.原型链
以一个例子来具体来看:
f是 通过构造函数Foo new的一个对象,他有一个自己的方法printName。同时构造函数还增加了一个方法的alertName。
Foo像一个类,而f是他类别下面一个具体的实例。
类的方法他都有,实例还有自己单独的方法。
function Foo(name,age){
this.name = name;
}
Foo.prototype.alertName= function(){
alert(this.name)
}
var f = new Foo('dd',13)
f.printName = function () {
console.log(this.name)
}
f
//Foo {name: "dd", printName: ƒ}
f.printName()
//dd
f.alertName()
f.toString()
//"[object Object]"
f
//Foo {name: "dd", printName: ƒ}
f.__proto__
//{alertName: ƒ, constructor: ƒ}
Object
//ƒ Object() { [native code] }
Object.prototype
//{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
f.__proto__.__proto__
/*{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
constructor: ƒ Object()
hasOwnProperty: ƒ hasOwnProperty()
isPrototypeOf: ƒ isPrototypeOf()
propertyIsEnumerable: ƒ propertyIsEnumerable()
toLocaleString: ƒ toLocaleString()
toString: ƒ toString()
valueOf: ƒ valueOf()
__defineGetter__: ƒ __defineGetter__()
__defineSetter__: ƒ __defineSetter__()
__lookupGetter__: ƒ __lookupGetter__()
__lookupSetter__: ƒ __lookupSetter__()
get __proto__: ƒ __proto__()
set __proto__: ƒ __proto__()*/
其中含有一个this,this要看具体的情形来判断的,当比如说f.name这个this就是指向f.
5.instanceof
用于判断引用类型属于哪个构造函数的方法
var arr = [1,2,3]
arr instanceof Array
//true
typeof arr
//"object"
问题解决:
-
如何准确判断一个变量是数组类型
instanceof -
写一个原型链继承的例子
function Elem(id){ this.ele = document.getElementById(id); } Elem.prototype.html = function (value) { var ele = this.ele; if (value) { ele.innerHTML = value; return this; }else { return ele.innerHTML } } Elem.prototype.on = function (type,fn) { var ele = this.ele; ele.addEventListener(type,fn); } var a = new Elem('article'); a.on('click',function() { alert('hello'); }); console.log(a.html());
这里的return this可以使得在后面调用时候,进行循环调用。
-
描述new 一个对象的过程
先传入相应的参数,也可以不传,然后在构造函数里面有一个this的空对象,对他进行扩展属性赋值,再返回一个this。将他返回给那个对象。 -
Zepto(或其他框架)源码中如何使用原型链
可以自行去查找相关资料看一下。