javascript继承
- 格式:doc
- 大小:189.50 KB
- 文档页数:54
前端开发工程师面试题及答案在前端开发领域,面试是选拔优秀人才的重要环节。
以下是一些常见的前端开发工程师面试题以及对应的参考答案。
一、HTML 和 CSS 相关问题1、解释一下盒模型以及它在布局中的作用。
答案:盒模型是 CSS 中用于布局的基本概念,它由内容(content)、内边距(padding)、边框(border)和外边距(margin)组成。
在布局中,理解盒模型对于准确计算元素的尺寸和间距非常重要,能够帮助我们实现各种复杂的页面布局。
2、如何实现一个两栏布局,左边固定宽度,右边自适应?答案:可以使用多种方法实现。
一种常见的方式是使用浮动(float),将左边栏设置为固定宽度并向左浮动,右边栏不浮动,并设置其左边的外边距(marginleft)为左边栏的宽度。
也可以使用 flex 布局,将父容器设置为 display: flex; ,左边栏设置固定宽度,右边栏设置flex: 1; 以实现自适应。
3、说一说 CSS 选择器的种类和优先级。
答案:CSS 选择器包括元素选择器、类选择器、id 选择器、属性选择器、伪类选择器、伪元素选择器等。
选择器的优先级从高到低依次为:内联样式(通过 style 属性设置)> id 选择器>类选择器、属性选择器、伪类选择器>元素选择器、伪元素选择器。
二、JavaScript 相关问题1、谈谈你对 JavaScript 中作用域和闭包的理解。
答案:作用域决定了变量的可见性和可访问性。
在 JavaScript 中有全局作用域和函数作用域。
闭包是指有权访问另一个函数作用域中的变量的函数。
闭包可以让函数记住其创建时的环境,即使外部函数已经执行完毕,闭包仍能访问外部函数中的变量。
2、如何实现 JavaScript 的继承?答案:常见的实现方式有原型链继承、借用构造函数继承、组合继承、寄生组合继承等。
原型链继承通过将子类型的原型指向父类型的实例来实现继承;借用构造函数继承通过在子类型的构造函数中调用父类型的构造函数来继承属性;组合继承结合了原型链继承和借用构造函数继承的优点;寄生组合继承是一种优化的组合继承方式,避免了不必要的父类实例属性的重复创建。
JS中的六种继承⽅式以及优缺点总结⽬录前⾔原型链继承构造函数继承组合继承(原型链继承和构造函数继承组合)寄⽣式继承组合寄⽣式继承extends继承总结前⾔继承是JS世界中必不可少的⼀个环节,号称JS的三座⼤⼭之⼀,使⽤这种⽅式我们可以更好地复⽤以前的开发代码,缩短开发的周期、提升开发效率在ES6之前,JS中的类都是通过构造函数模拟的,并不存在真正意义上的类,虽然ES6的类知识⼀个语法糖 ,这个时期的类是可以当作函数直接使⽤的,到了ES6之后,类是不可以再当作函数使⽤了在开始聊继承之前,⾸先需要明确的是类中存在两种属性:实例上的属性和公共属性,接下来谈到的所有继承⽅式都是围绕这两点来展开function Animal(name) {// 实例上的属性 = name;}// 公共属性Animal.prototype.eat = function() {// todo ...}如何避免将ES6之前的构造函数直接当作函数调⽤?ES5时期解决⽅案:function Animal() {// 若是直接调⽤, 不是使⽤ new调⽤, 抛出异常if (!(this instanceof Animal)) {// new的原理, 使⽤new的时候, this是Animal的实例, 则 this instanceof Animal 为truethrow new Error("请勿直接调⽤构造函数");}}ES6之后解决⽅案:function Animal() {// 若是使⽤new, 则new.target指向⾃⾝, 否则为undefined, 但是在继承的时候不能使⽤,因为继承实例上属性的时候, 原来的es5是使⽤ Animal.call(this)的⽅式 if (!new.target) {throw new Error("请勿直接调⽤构造函数");}}上述两种⽅案都可以解决直接当作函数调⽤,若是直接调⽤控制台会报错:Uncaught Error: 请勿直接调⽤构造函数接下来便⼀起看看JS中有哪些继承⽅式原型链继承原型链继承是⽐较常见的继承⽅式之⼀,其中涉及的构造函数、原型和实例,三者之间存在着⼀定的关系,即每⼀个构造函数都有⼀个原型对象,原型对象⼜包含⼀个指向构造函数的指针,⽽实例则包含⼀个原型对象的指针。
js 继承方式JavaScript是一门动态语言,它的继承机制与其他静态语言的继承机制有所不同。
在 JavaScript 中,我们可以通过一些方式来实现继承,如原型链、构造函数、组合继承等。
本文将详细介绍这些继承方式,并对它们进行比较和应用场景的分析。
一、原型链继承原型链继承是 JavaScript 中最基本的继承方式之一。
它的实现原理是通过将一个对象的原型指向另一个对象来实现继承。
我们可以通过以下代码来实现原型链继承:```javascriptfunction Parent() { = 'parent';}Parent.prototype.sayName = function() {console.log();}function Child() {}Child.prototype = new Parent();var child = new Child();child.sayName(); // 输出 'parent'```在上面的代码中,我们定义了一个 Parent 构造函数,并在它的原型上添加了一个 sayName 方法。
然后,我们定义了一个 Child 构造函数,并将它的原型指向 Parent 的实例。
最后,我们创建了一个Child 的实例,并调用了 sayName 方法。
可以看到,这个实例可以调用到 Parent 的属性和方法。
原型链继承的优点是非常简单,只需要一个简单的赋值操作即可实现继承。
但是,它也有一些缺点。
首先,它会导致所有子类实例共享同一个父类实例。
这意味着,如果一个子类实例修改了父类实例的属性或方法,其他子类实例也会受到影响。
其次,它无法向父类构造函数传递参数,这使得在创建子类实例时无法对父类进行初始化。
因此,原型链继承并不是一个非常完美的继承方式,我们需要考虑其他的继承方式。
二、构造函数继承构造函数继承是通过在子类构造函数内部调用父类构造函数来实现继承。
javascript 继承禁用方法在JavaScript 中,继承是通过原型链来实现的。
如果你想在子类中禁用(覆盖)父类的方法,可以在子类中重新定义该方法。
以下是一个简单的示例:javascriptCopy code// 父类function Animal(name) { = name;}// 父类方法Animal.prototype.sayHello = function() {return `Hello, I'm ${}`;};// 子类继承父类function Cat(name, color) {Animal.call(this, name);this.color = color;}// 子类继承父类的原型Cat.prototype = Object.create(Animal.prototype);// 子类禁用父类方法Cat.prototype.sayHello = function() {return "I'm a cat, I don't want to say hello!";};// 创建子类实例var myCat = new Cat("Whiskers", "gray");// 调用禁用的方法console.log(myCat.sayHello()); // 输出: "I'm a cat, I don't want to say hello!"在上述例子中,Cat 类继承了Animal 类,并通过重新定义sayHello 方法来禁用了父类的同名方法。
在实际应用中,你可以根据需要在子类中重新定义方法来实现禁用。
请注意,这样的做法可能会导致一定的代码可维护性问题,因为子类覆盖了父类的方法。
在设计时需要谨慎使用。
JavaScript组合继承详解⽬录1、前⾔2、原型链继承3、构造函数继承4、组合继承1、前⾔⾸先学习继承之前,要对原型链有⼀定程度的了解。
不了解可以去先阅读我另⼀篇⽂章,⾥⾯对原型链有⼀个较为详细的说明:。
如果已经了解请继续。
之前写过⼀篇博⽂将继承⽅式全部列出来了,不过我发现⼀⼝⽓看完过于长了,也不利于吸收知识,所以我先将组合继承部分划分出来,后续会把寄⽣部分补上。
2、原型链继承⽗类实例作为⼦类的原型⼦类创造的两个实例的隐式原型__proto__指向⽗类的那个实例⽽⽗类的实例的隐式原型__proto__⼜指向⽗类的原型father.prototype根据原型链的特性,所有⼦类的实例能够继承⽗类原型上的属性。
阅览以下这张图可以配合代码理解清晰://⽗类function father() {this.fatherAttr = ["fatherAttr"];}//⽗类的原型上的属性father.prototype.checkProto = "checkProto";//⼦类function child() {}// 将father实例作为child这个构造函数的原型child.prototype = new father();child.prototype.constructor = child;//两个⼦类实例const test1 = new child();const test2 = new child();console.log("测试1:");console.log("test1:", test1);console.log("test2:", test2);console.log("test1.fatherAttr:", test1.fatherAttr);console.log("test2.fatherAttr:", test2.fatherAttr);console.log("测试2:");test1.fatherAttr.push("newAttr");console.log("test1.fatherAttr:", test1.fatherAttr);console.log("test2.fatherAttr:", test2.fatherAttr);console.log("测试3:");console.log("test1.checkProto:", test1.checkProto);特点:两个实例对象都没有fatherAttr属性,但是因为⽗类的实例会拥有fatherAttr属性,且现在⽗类的实例作为child的原型,根据原型链,他们可以共享到⾃⼰的构造函数child的原型上的属性。
js 继承相关的面试题在JavaScript中,继承是一种机制,允许一个对象继承另一个对象的属性和方法。
以下是一些关于JavaScript继承的面试题:1. 什么是JavaScript中的继承?2. 有哪些JavaScript继承的方法?3. 解释一下原型链和基于原型的继承。
4. 什么是构造函数?在JavaScript中如何使用构造函数?5. 什么是原型?原型在JavaScript中的作用是什么?6. 什么是`this`关键字?在JavaScript中如何使用`this`关键字?7. 解释一下JavaScript中的`call()`、`apply()`和`bind()`方法。
8. 解释一下`()`方法。
9. 解释一下`()`和`()`方法。
10. 什么是`instanceof`操作符?在JavaScript中如何使用`instanceof`操作符?11. 解释一下JavaScript中的类(Class)和继承。
12. 在JavaScript中,如何实现继承?13. 你能解释一下JavaScript中的`super`关键字吗?14. 在ES6中,如何使用类(Class)和继承?15. 你能解释一下JavaScript中的继承和原型链的关系吗?16. 在JavaScript中,如何使用原型和原型链实现继承?17. 你能解释一下JavaScript中的`()`方法吗?18. 你能解释一下JavaScript中的`()`和原型链的关系吗?19. 你能解释一下JavaScript中的`()`和原型链的关系吗?20. 你能解释一下JavaScript中的类(Class)和原型的关系吗?。
js实现继承的方法在 JavaScript 中,实现继承的方法有三种:原型链继承、构造函数继承和组合继承。
1. 原型链继承原型链继承是最基本的实现继承的方式。
它通过将父类的实例作为子类的原型,从而实现子类继承父类的属性和方法。
实现代码如下:```function Parent() { = '张三';}Parent.prototype.getName = function() {return ;}function Child() {}Child.prototype = new Parent();var child = new Child();console.log(child.getName()); // 输出:张三```这种方式存在一个问题,就是所有子类实例都会共用一个父类实例。
如果一个子类实例修改父类的属性或方法,那么所有子类实例都会受到影响。
2. 构造函数继承构造函数继承是通过在子类构造函数内部调用父类构造函数的方式,来实现子类继承父类的属性和方法。
实现代码如下:```function Parent() { = '张三';}Parent.prototype.getName = function() {return ;}function Child() {Parent.call(this);}var child = new Child();console.log(child.getName()); // 输出:undefined```这种方式解决了原型链继承存在的问题,但是它也存在一个问题,就是父类原型上的方法无法被子类继承。
因为子类的原型是空对象,而不是父类的原型。
3. 组合继承组合继承是将原型链继承和构造函数继承结合起来的方式,从而既能够继承父类的属性和方法,又能够继承父类原型上的方法。
实现代码如下:```function Parent() { = '张三';Parent.prototype.getName = function() {return ;}function Child() {Parent.call(this);}Child.prototype = new Parent();Child.prototype.constructor = Child;var child = new Child();console.log(child.getName()); // 输出:张三```这种方式既能够继承父类的属性和方法,又能够继承父类原型上的方法。
javascript原型链理解
JavaScript原型链是一种机制,用于实现对象之间的继承。
在JavaScript中,每个对象都有一个原型对象,而原型对象本身也是一个对象,拥有自己的原型对象,形成一条原型链。
通过原型链,可以实现属性和方法的继承。
具体来说,当访问一个对象的属性或方法时,如果对象本身没有该属性或方法,JavaScript就会沿着原型链向上查找,直到找到该属性或方法或者原型链的顶端(null)为止。
这样的话,对象可以共享原型对象上的属性和方法。
原型链主要有以下几个要点:
1. 每个对象都有一个隐式原型(__proto__),指向创建它的构造函数的原型对象。
2. 所有对象的原型对象最终都指向Object.prototype,即Object构造函数的原型对象。
3. Object.prototype的原型为null,表示原型链的顶端。
通过原型链,JavaScript实现了对象之间的继承。
当我们创建一个对象时,可以通过设置该对象的隐式原型指向一个已有对象,从而使其继承该对象的属性和方法。
这样可以减少重复的代码,提高代码的复用性。
需要注意的是,原型链在对象的访问过程中是动态的,即使我们修改了原型对象上的属性或方法,所有继承该原型对象的对象也会受到影响。
这是因为对象的原型链是在对象访问时动态决定的。
总之,原型链是JavaScript中实现对象继承的重要机制,通过原型链可以实现对象的属性和方法的继承,并提高代码的复用性。
js父类调用子类方法JS父类调用子类方法在JavaScript中,我们可以通过继承来实现代码的复用和扩展。
在继承中,父类可以调用子类的方法,这在某些场景下非常有用。
本文将介绍如何在JS中实现父类调用子类方法。
首先,我们需要了解JS中的继承方式。
JS中的继承有两种方式:原型继承和类继承。
在原型继承中,我们可以通过将子类的原型指向父类的实例来实现继承。
在类继承中,我们可以使用ES6中的class关键字来定义类,并使用extends关键字来实现继承。
在原型继承中,父类可以通过调用子类的原型方法来调用子类的方法。
例如:```javascriptfunction Parent() {}Parent.prototype.sayHello = function() {console.log('Hello from parent');}function Child() {}Child.prototype = Object.create(Parent.prototype);Child.prototype.constructor = Child;Child.prototype.sayHello = function() {console.log('Hello from child');}const child = new Child();child.sayHello(); // 输出:Hello from childParent.prototype.sayHello.call(child); // 输出:Hello from child ```在上面的例子中,我们定义了一个父类Parent和一个子类Child。
我们将Child的原型指向Parent的实例,并重写了Child的sayHello 方法。
在调用child.sayHello()时,输出的是子类的sayHello方法。
而在调用Parent.prototype.sayHello.call(child)时,输出的也是子类的sayHello方法。
js继承的几种方法class在JavaScript中,使用`class`关键字可以实现面向对象编程中的继承。
以下是通过`class`实现继承的几种常见方法:1. 基本的`class`继承:```javascriptclass Animal {constructor(name) { = name;}speak() {console.log(`${} makes a sound.`);}}class Dog extends Animal {speak() {console.log(`${} barks.`);}}const dog = new Dog('Buddy');dog.speak(); // 输出: Buddy barks.```2. 调用`super`关键字:使用`super`关键字可以在子类的构造函数中调用父类的构造函数,并访问父类的方法。
```javascriptclass Animal {constructor(name) { = name;}speak() {console.log(`${} makes a sound.`);}}class Dog extends Animal {constructor(name, breed) {super(name);this.breed = breed;}speak() {super.speak();console.log(`${} barks.`);}}const dog = new Dog('Buddy', 'Golden Retriever');dog.speak(); // 输出: Buddy makes a sound. Buddy barks.```3. 使用`Object.create`:使用`Object.create`方法可以实现原型链继承。
```javascriptconst Animal = {init: function(name) { = name;return this;},speak: function() {console.log(`${} makes a sound.`);}};const Dog = Object.create(Animal);Dog.init = function(name, breed) {Animal.init.call(this, name);this.breed = breed;return this;};Dog.speak = function() {Animal.speak.call(this);console.log(`${} barks.`);};const dog = Dog.init('Buddy', 'Golden Retriever');dog.speak(); // 输出: Buddy makes a sound. Buddy barks.```这些是在JavaScript中使用`class`关键字实现继承的几种常见方法。
javascript继承当代码var zhang = new Person("ZhangSan", "man")执行时,其实内部做了如下几件事情:∙创建一个空白对象(new Object())。
∙拷贝Person.prototype中的属性(键值对)到这个空对象中(我们前面提到,内部实现时不是拷贝而是一个隐藏的链接)。
∙将这个对象通过this关键字传递到构造函数中并执行构造函数。
∙将这个对象赋值给变量zhang。
上面关于继承的实现很粗糙,并且存在很多问题:∙在创建Employee构造函数和原型(以后简称类)时,就对Person进行了实例化,这是不合适的。
∙Employee的构造函数没法调用父类Person的构造函数,导致在Employee构造函数中对name和sex属性的重复赋值。
∙Employee中的函数会覆盖Person中的同名函数,没有重载的机制(和上一条是一个类型的问题)。
∙创建JavaScript类的语法过于零散,不如C#/Java中的语法优雅。
∙实现中有constructor属性的指向错误,这个会在第二篇文章中讨论。
我们会在第三章完善这个例子。
JavaScript继承的实现正因为JavaScript本身没有完整的类和继承的实现,并且我们也看到通过手工实现的方式存在很多问题,因此对于这个富有挑战性的任务网上已经有很多实现了:∙this∙this表示当前对象,如果在全局作用范围内使用this,则指代当前页面对象window;如果在函数中使用this,则this指代什么是根据运行时此函数在什么对象上被调用。
我们还可以使用apply和call两个全局方法来改变函数中this的具体指向。
∙先看一个在全局作用范围内使用this的例子:∙∙函数中的this是在运行时决定的,而不是函数定义时,如下:∙∙全局函数apply和call可以用来改变函数中this的指向,如下:∙注:apply和call两个函数的作用相同,唯一的区别是两个函数的参数定义不同。
∙∙因为在JavaScript中函数也是对象,所以我们可以看到如下有趣的例子:∙∙prototype∙我们已经在第一章中使用prototype模拟类和继承的实现。
prototype本质上还是一个JavaScript对象。
并且每个函数都有一个默认的prototype属性。
如果这个函数被用在创建自定义对象的场景中,我们称这个函数为构造函数。
比如下面一个简单的场景:∙作为类比,我们考虑下JavaScript中的数据类型- 字符串(String)、数字(Number)、数组(Array)、对象(Object)、日期(Date)等。
我们有理由相信,在JavaScript 内部这些类型都是作为构造函数来实现的,比如:∙同时对数组操作的很多方法(比如concat、join、push)应该也是在prototype属性中定义的。
实际上,JavaScript所有的固有数据类型都具有只读的prototype属性(这是可以理解的:因为如果修改了这些类型的prototype属性,则哪些预定义的方法就消失了),但是我们可以向其中添加自己的扩展方法。
∙注意:这里有一个陷阱,向Array的原型中添加扩展方法后,当使用for-in循环数组时,这个扩展方法也会被循环出来。
下面的代码说明这一点(假设已经向Array的原型中扩展了min方法):∙解决方法也很简单:∙∙constructor∙constructor始终指向创建当前对象的构造函数。
比如下面例子:∙∙但是当constructor遇到prototype时,有趣的事情就发生了。
我们知道每个函数都有一个默认的属性prototype,而这个prototype的constructor 默认指向这个函数。
如下例所示:∙当时当我们重新定义函数的prototype时(注意:和上例的区别,这里不是修改而是覆盖),constructor的行为就有点奇怪了,如下示例:∙为什么呢?原来是因为覆盖Person.prototype时,等价于进行如下代码操作:∙而constructor始终指向创建自身的构造函数,所以此时Person.prototype.constructor === Object,即是:∙怎么修正这种问题呢?方法也很简单,重新覆盖Person.prototype.constructor即可:∙∙在第一章中,我们使用构造函数和原型的方式在JavaScript的世界中实现了类和继承,但是存在很多问题。
这一章我们将会逐一分析这些问题,并给出解决方案。
∙注:本章中的jClass的实现参考了Simple JavaScript Inheritance的做法。
∙首先让我们来回顾一下第一章中介绍的例子:∙修正constructor的指向错误∙∙从上一篇文章中关于constructor的描述,我们知道Employee实例的constructor 会有一个指向错误,如下所示:∙我们需要简单的修正:∙创建Employee类时实例化Person是不合适的∙∙但另一方面,我们又必须依赖于这种机制来实现继承。
解决办法是不在构造函数中初始化数据,而是提供一个原型方法(比如init)来初始化数据。
∙这种方式下,必须在实例化一个对象后手工调用init函数,如下:∙∙如何自动调用init函数?∙∙必须达到两个效果,构造类时不要调用init函数和实例化对象时自动调用init函数。
看来我们需要在调用空的构造函数时有一个状态标示。
∙但是这样就必须引入全局变量,这是一个不好的信号。
∙∙如何避免引入全局变量initializing?∙∙我们需要引入一个全局的函数来简化类的创建过程,同时封装内部细节避免引入全局变量。
∙使用jClass函数来创建类和继承类的方法:∙OK,现在创建类和实例化类的方式看起来优雅多了。
但是这里面还存在明显的瑕疵,Employee的初始化函数init无法调用父类的同名方法。
∙∙如何调用父类的同名方法?∙∙我们可以通过为实例化对象提供一个base的属性,来指向父类(构造函数)的原型,如下:∙调用方式:∙∙目前为止,我们已经修正了在第一章手工实现继承的种种弊端。
通过我们自定义的jClass函数来创建类和子类,通过原型方法init初始化数据,通过实例属性base来调用父类的原型函数。
∙唯一的缺憾是调用父类的代码太长,并且不好理解,如果能够按照如下的方式调用岂不是更妙:∙∙优化jClass函数∙∙此时,创建类与子类以及调用方式都显得非常优雅,请看:∙∙至此,我们已经创建了一个完善的函数jClass,帮助我们在JavaScript中以比较优雅的方式实现类和继承。
这里面有几处不得不提的硬伤:∙子类从父类继承的代码必须在子类和父类都定义好之后进行,并且必须在子类原型方法定义之前进行。
∙虽然子类方法体中可以调用父类的方法,但是子类的构造函数无法调用父类的构造函数。
∙代码的书写不够优雅,比如原型方法的定义以及调用父类的方法(不直观)。
当然Crockford的实现还支持子类中的方法调用带参数的父类方法,如下例子:代码分析首先method函数的定义就很简单了:要特别注意这里this的指向。
当我们看到this时,不能仅仅关注于当前函数,而应该想到当前函数的调用方式。
比如这个例子中的method我们不会通过new的方式调用,所以method 中的this指向的是当前函数。
inherits函数的定义有点复杂:注意,在inherits函数中还有一个小小的BUG,那就是没有重定义constructor的指向,所以会发生如下的错误:改进建议根据前面的分析,个人觉得method函数必要性不大,反而容易混淆视线。
而inherits方法可以做一些瘦身(因为Crockford可能考虑更多的情况,原文中介绍了好几种使用inherits的方式,而我们只关注其中的一种),并修正了constructor的指向错误。
调用方式:有点意思在文章的结尾,Crockford居然放出了这样的话:I have been writing JavaScript for 8 years now, and I have never once found need to use an uber function. The super idea is fairly important in the classical pattern, but it appears to be unnecessary in the prototypal and functional patterns. I now see my early attempts to support the classical model in JavaScript as a mistake.可见Crockford对在JavaScript中实现面向对象的编程不赞成,并且声称JavaScript应该按照原型和函数的模式(the prototypal and functional patterns)进行编程。
不过就我个人而言,在复杂的场景中如果有面向对象的机制会方便的多。
但谁有能担保呢,即使像jQuery UI这样的项目也没用到继承,而另一方面,像Extjs、Qooxdoo 则极力倡导一种面向对象的JavaScript。
甚至Cappuccino项目还发明一种Objective-J语言来实践面向对象的JavaScript。
在本章中,我们将分析John Resig关于JavaScript继承的一个实现- Simple JavaScript Inheritance。
John Resig作为jQuery的创始人而声名在外。
是《Pro JavaScript Techniques》的作者,而且Resig将会在今年秋天推出一本书《JavaScript Secrets》,非常期待。
调用方式调用方式非常优雅:注意:代码中的Class、extend、_super都是自定义的对象,我们会在后面的代码分析中详解。
说实话,对于完成本系列文章的目标-继承-而言,真找不到什么缺点。
方法一如jQuery一样简洁明了。
代码分析为了一个漂亮的调用方式,内部实现的确复杂了很多,不过这些也是值得的- 一个人的思考带给了无数程序员快乐的微笑- 嘿嘿,有点肉麻。
不过其中的一段代码的确迷惑我一段时间:我曾在几天前的博客中写过一篇文章专门阐述这个问题,有兴趣可以向前翻一翻。
下面我会对其中的for-in循环进行解读,把自执行的匿名方法用一个局部函数来替换,这样有利于我们看清真相:写到这里,大家是否觉得Resig的实现和我们在第三章一步一步实现的jClass很类似。