首页 > 代码库 > js继承相关

js继承相关

这几天看到一篇文章详解Javascript的继承实现,发现js还是很深奥的,比如call、apply、prototype这些,问起来我也能说的头头是道的,但是看到一些复杂的代码有的时候还是会迷糊,所以查了好多资料,希望下次我也能用在代码中,写出优秀的代码,大神,我来了,哈哈哈哈哈......

1.call apply

func.call(newObj,arg1,arg2);

func.apply(newObj,[arg1,arg2]);

ecma中为了实现继承机制中的对象冒充,加入了call()和apply()两个方法。以call为例,call方法需要传入两个参数,第一个参数是this的值,第二个参数是传递给this指代的函数的值,为了改变函数内部的this指向,将函数的上下文改变为制定的新对象newObj。

function sayColor(sPrefix,sSuffix) {
    alert(sPrefix + this.color + sSuffix);
};

var obj = new Object();
obj.color = "blue";
//改变sayColor中this的指向为obj,将sayColor作为obj的一个方法。
sayColor.call(obj, "The color is ", "a very nice color indeed.");

2.this.init.apply(this, arguments)

技术分享

看代码的时候,发现有这么一段代码,init是定义中构造函数原型链上的方法,这里的两个this指向构造函数实例化之后的对象,这句代码的意思是当满足条件判断的时候,实例化之后的对象就会执行init方法进行初始化,并且传入arguments参数(arguments中的参数必须与init方法中的参数相匹配)。

 3.Object.prototype.hasOwnProperty()

 官方解释是看某个对象是否含有指定的自身属性。所有继承了prototype属性的对象都会从原型链上继承到 hasOwnProperty 方法,该方法会忽略掉那些从原型链上继承到的属性。

技术分享

copy方法遍历原型链上各个方法,赋值并返回该对象。

4.对象引用

看到这样一句话,以下为引用部分

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

//用来复制父类原型,由于父类原型上约定只写实例方法,所以复制的时候不必担心引用的问题
var copy = function (source) {
    var target = {};
    for (var i in source) {
        if (source.hasOwnProperty(i)) {
            target[i] = source[i];
        }
    }
    return target;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
不明白为什么,只复制实例方法不必担心引用的问题,查资料后发现,引用是一个非常深奥的问题。希望以后能深入了解。
5.this.base()
为了实现在每个实例方法里,都能通过this.base()调用父类原型上相应的方法,该方法实现调用了一个匿名函数中返回的函数。

  this.base()这个方法是通过一个匿名函数实现的,可以看到匿名函数实现的代码可读性非常强,代码结构也是很清晰的。

 以下是它的经典实例。

//不使用立即执行函数表达式,在鼠标点击事件开始前,for循环已经完成
每次点击结果都为li集合的索引最大值
var li=document.getElementsByTagName(‘li‘);  
for (var i=0; i<li.length; i++) {
 //将当前的i作为参数传入匿名函数,将i的值保存在内存中,
  (function(i){
        li[i].onclick = function () {
            console.log(i);
        };
   })(i);
}
//或者以下写法
var li=document.getElementsByTagName(‘li‘);  
for (var i=0; i<li.length; i++) {
 //将当前的i作为参数传入匿名函数,将i的值保存在内存中,
    li[i].onclick = function (i) {
        return function(){
              console.log(i);
        }
    }(i);
}
        

 匿名函数又叫立即执行函数表达式(Immediately-Invoked Function Expression (IIFE)),写法如下:

 

//多种写法
//第一种写法外面加个括号,原因是如果代码量很大,我们需要滚动到最底部去判断i是个function还是function的返回值。
var i = (function(){//代码}())
var i = (function(){//代码})()

 

闭包的定义是有权访问另一个作用域中的变量的函数,匿名函数也是这样的原理,匿名函数的第二个括号里面的参数传入参数,使得函数能够引用外部函数的变量,基于这个原理,我们能保存变量的状态。想了解匿名函数执行原理以及匿名函数作用域的,可看下JS----匿名函数这篇文章,我从中学到了很多,多谢园子里的大神们!

技术分享

再回到javascript的继承实现,再看这个函数就很好理解了。

子类原型链的init方法用()括起来,里面是一个匿名函数,匿名函数传入两个参数(init和func),如果实例有base属性,就把它赋值给old变量。再把实例的base属性指向父类原型的init方法,func函数内部就可以通过this.base调用父类原型的方法。

小结:

javascript是一门深奥的语言,到了某个阶段会发现懂得的东西都只是皮毛,希望通过大神的指引能很快渡过这段时间,也希望我尽快减肥成功!

 

参考文章

1.【优雅代码】深入浅出 妙用Javascript中apply、call、bind

2.解析 this.initialize.apply(this, arguments)

3.js 对象深复制,创建对象和继承

4.js 匿名函数 闭包

5.JS----匿名函数
6.详解javascript立即执行函数表达式(IIFE)
 

js继承相关