https://www.jmqz1000.com

JavaScript原型和原型链的方法介绍(代码示例)

本篇文章给大家带来的内容是关于JavaScript原型和原型链的方法介绍(代码示例),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。

1、题目

如何准确判断一个变量是数组

写一个原型链继承的例子

继承实现的其他方式

es6 实现继承的底层原理是什么

描述new一个对象的过程

zepto及其他源码中如何使用原型链

2.知识点

2.1 html' target='_blank'>构造函数

特点:以大写字母开头

function Foo(name,age){
 //var obj = {}
 //this = {}
 this.name = name;
 this.age = age;
 this.class = class1 
 // return this
var f1 = new Foo( liming ,19);

扩展

var o = {} 是 var o = new Object() 的语法糖

var a = [] 是 var a = new Array() 的语法糖

function Foo(){} 相当于 var Foo = new Function(){}

2.2 原型规则

五条规则:

1.所有引用类型(对象,数组,函数)都具有对象特性,即可以自由扩展属性

2.所有引用类型(对象,数组,函数)都具有一个__proto__(隐式原型)属性,是一个普通对象

3.所有的函数都具有prototype(显式原型)属性,也是一个普通对象

4.所有引用类型(对象,数组,函数)__proto__值指向它构造函数的prototype

5.当试图得到一个对象的属性时,如果变量本身没有这个属性,则会去他的__proto__中去找

for (var key in object) {
 //高级浏览器中已经屏蔽了来自原型的属性
 //建议加上判断保证程序的健壮性
 if (object.hasOwnProperty(key)) {
 console.log(object[key]);
}

2.3 原型链

obj.__ proto . proto . proto __ ...

Object.prototype === null

instanceof 用于判断引用类型属于哪个构造函数

obj instanceob Foo

实际意义:判断 Foo.prototype 在不在 obj的原型链上

3.题目解答

3.1 如何准确判断一个变量是数组

arr instanceof Array

3.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,fun){
 var elem = this.elem;
 elem.addEventListener(type,fun);
 return this;
var p1 = new Elem( id1 
p1.html( test ).on( click ,function(){
 console.log( 点击 
})

3.3 继承实现的其他方式

3.3.1 原型继承

 var obj = {
 0: a ,
 1: b ,
 arr:[1]
 function Foo(arr2){
 this.arr2 = [1]
 Foo.prototype = obj;
 var foo1 = new Foo();
 var foo2 = new Foo();
 foo1.arr.push(2);
 foo1.arr2.push(2);
 console.log(foo2.arr); //[1,2]
 console.log(foo2.arr2); //[1]

优点:实现简单

缺点:

1.无法向父类构造函数传参

2.同时new两个对象时改变一个对象的原型中的引用类型的属性时,另一个对象的该属性也会修改。因为来自原型对象的引用属性是所有实例共享的。

3.3.2 构造继承
 function Super(b){
 this.b = b;
 this.fun = function(){}
 function Foo(a,b){
 this.a = a;
 Super.call(this,b);
 var foo1 = new Foo(1,2);
 console.log(foo1.b);

优点:可以向父类传参,子类不会共享父类的引用属性

缺点:无法实现函数复用,每个子类都有新的fun,太多了就会影响性能,不能继承父类的原型对象。

3.3.3 组合继承
function Super(){
 // 只在此处声明基本属性和引用属性
 this.val = 1;
 this.arr = [1];
// 在此处声明函数
Super.prototype.fun1 = function(){};
Super.prototype.fun2 = function(){};
//Super.prototype.fun3...
function Sub(){
 Super.call(this); // 核心
 // ...
Sub.prototype = new Super();

优点:不存在引用属性共享问题,可传参,函数可复用

缺点:父类的属性会被实例化两次,获取不到真正实例父类(无法区分实例是父类创建还是父类创建的)

优化:

 function Super(b){
 this.b = b;
 this.fun = function(){}
 Super.prototype.c = function(){console.log(1111)}
 function Foo(a,b){
 this.a = a;
 Super.call(this,b);

//修复构造函数: var foo1 = new Foo(1,2);

缺点:无法区分实例是父类创建还是子类创建的

3.3.4 寄生组合继承
 function Super(b){
 this.b = b;
 Super.prototype.c = function(){console.log(1111)}
 function Foo(a,b){
 this.a = a;
 Super.call(this,b);
 var f = new Function();
 f.prototype = Super.prototype;
 Foo.prototype = new f();
 //等同于 Foo.prototype = Object.create(Super.prototype);
 var foo1 = new Foo(1,2);

对父类的prototype进行一次寄生,即包装成一个空对象的prototype,再把这个对象实例化出来作为子类的peototype。

缺点:无法区分实例是父类创建还是子类创建的

可以添加以下代码:

Foo.prototype.constructor = Foo

这种解决方法不能用于上面的组合优化方法,因为子类父类引用的是同一个原型对象,修改会同时修改。

总结:

继承主要是实现子类对父类方法,属性的复用。

来自原型对象的引用属性是所有实例共享的,所以我们要避免从原型中继承属性。

在构造函数中通过call函数可以继承父类构造函数的属性和方法,但是通过这种方式实例化出来的实例会将父类方法多次存储,影响性能。

通过组合继承我们使用call继承属性,使用原型继承方法,可以解决以上两个问题,但是通过这种方式实例化出来的对象会存储两份父类构造函数中的属性。

用父类的原型构造一个新对象作为子类的原型,就解决了多次存储的问题,所以最终的寄生组合继承就是最佳继承方式,它的缺点就是书写起来比较麻烦。

3.3.6 node源码中的继承实现
function inherits(ctor, superCtor) {
 ctor.super_ = superCtor;
 ctor.prototype = Object.create(superCtor.prototype, {
 constructor: {
 value: ctor,
 enumerable: false,
 writable: true,
 configurable: true
function Stream(){
 //...
function OutgoingMessage() {
 Stream.call(this);
 //...
inherits(OutgoingMessage, Stream);
OutgoingMessage.prototype.setTimeout = ...

以上是寄生组合继承的一个实例。

1.在OutgoingMessage构造函数中通过call继承Stream构造中的属性。

2.调用inherits方法继承Stream原型中的属性。

3.扩展OutgoingMessage自身原型的函数。

inherits方法中使用了Object.create方法,该方法的作用是通过指定的原型对象和属性创建一个新的对象。

ctor.prototype=Object.create(superCtor.prototype,{.....});

该方法实际上就做了我们上面寄生组合继承中的工作

var f = new Function();
f.prototype =superCtor.prototype;
return new f();

后面的参数是给原型对象添加属性,可选属性(非必填),即把自身作为新创建对象的构造函数。

value: 表示constructor 的属性值;
writable: 表示constructor 的属性值是否可写;[默认为: false]
enumerable: 表示属性constructor 是否可以被枚举;[默认为: false]
configurable: 表示属性constructor 是否可以被配置,例如 对obj.a做 delete操作是否允许;[默认为: false]
3.4 es6继承的实现方式

参考我这篇文章:http://segmentfault.com/a/11...

3.5 描述new一个对象的过程

创建一个对象

{}._proto_ = 构造函数.prototype

this指向这个对象

执行代码即对this赋值

返回this

3.6 zepto及其他源码中如何使用原型链
var Zepto = (function(){
 var $,zepto = {}
 // ...省略N行代码...
 $ = function(selector, context){
 return zepto.init(selector, context)
 zepto.init = function(selector, context) {
 var dom
 // 针对参数情况,分别对dom赋值
 // 最终调用 zepto.Z 返回的数据
 return zepto.Z(dom, selector)
 fnction Z(dom, selector) {
 var i, len = dom ? dom.length : 0
 for (i = 0; i len; i++) this[i] = dom[i]
 this.length = len
 this.selector = selector || 
 zepto.Z = function(dom, selector) {
 return new Z(dom, selector)
 $.fn = {
 // 里面有若干个工具函数

独孤九贱(5)_ThinkPHP5视频教程

ThinkPHP是国内最流行的中文PHP开发框架,也是您Web项目的最佳选择。《php.cn独孤九贱(5)-ThinkPHP5视频教程》课程以ThinkPHP5最新版本为例,从最基本的框架常识开始,将...

Peter-Zhu 2017-05-16 12:03:57


独孤九贱(4)_PHP视频教程

江湖传言:PHP是世界上最好的编程语言。真的是这样吗?这个梗究竟是从哪来的?学会本课程,你就会明白了。 PHP学知网出品的PHP入门系统教学视频,完全从初学者的角度出发,绝不玩虚的,一切以实用、有用...

Peter-Zhu 2017-03-20 22:47:17


独孤九贱(1)_HTML5视频教程

《php.cn原创html5视频教程》课程特色:php学知网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了HTML知识。 ...

Peter-Zhu 2017-03-13 10:15:11


ThinkPHP5实战之[教学管理系统]

本套教程,以一个真实的学校教学管理系统为案例,手把手教会您如何在一张白纸上,从零开始,一步一步的用ThinkPHP5框架快速开发出一个商业项目。

Peter-Zhu 2017-07-24 16:48:56


PHP入门视频教程之一周学会PHP

所有计算机语言的学习都要从基础开始,《PHP入门视频教程之一周学会PHP》不仅是PHP的基础部分更主要的是PHP语言的核心技术,是学习PHP必须掌握的内容,任何PHP项目的实现都离不开这部分的内容,通...

其它编程语言

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

相关文章阅读