首页 > 编程语言 >深入学习jquery源码之继承方案的选择

深入学习jquery源码之继承方案的选择

时间:2023-02-23 22:06:21浏览次数:34  
标签:jquery function name 继承 源码 call apply 参数 方法


prototype实现继承

原型链继承的主要思想是:让子类型的引用指向父类型的实例。

每次在函数(类)中定义了成员方法,都会导致实例有副本,因此可以借助prototype原型,进行改进

先访问自己本身的方法,没有再访问自己原型的方法,本身原型没有访问父类,父类没有,访问父类的原型方法...继续往上

Object.prototype.say=function  () { //最上层定义say的方法
alert("我是顶层的方法");
}

function person () {
this.say=function () {
alert("我是父类的方法");//先访问本身方法,再访问原型方法
}
}

person.prototype.say=function () {
alert("我是父类原型的方法");
}

function study () {
this.say=function () {
alert("本身的方法");
}
}

//继承person
study.prototype=new person();


study.prototype.say=function () {
alert("本身原型的方法");
}

var zhangsan=new study ();
alert(zhangsan.say)//我是父类原型的方法 父类有方法,不再向顶层找方法

使用这种方式,生成的实例既是子类实例,又是父类的实例

子类访问父类型原型链属性和方法

通过原型链继承的子类,可以直接访问到父类原型链上新增的方法和属性。

原型链继承缺点:

无法实现多继承

从原型链继承的代码来看,子类的prototype属性只能指向一个父类的实例,因此只能实现单继承。

父类引用属性是共享的

父类的值类型属性在生成的每个子实例中是独有的,而对应的引用类型属性则是每个实例共享的,这个问题对于原型链继承的影响是致命的。

引用类型属性共享问题

通过call方法调用父类的构造方法,并通过this改变构造方法的指向,this就指向了cat了。

var obj1={
name:"java"
}

window.name="javascript";
var func=function(){
console.log(this.name);
}

func(); //javasript
func.call(obj1); //java

深入学习jquery源码之继承方案的选择_数组

深入学习jquery源码之继承方案的选择_父类_02

name属性的修改,两者子类型实例name属性是不同的;而对于features属性的修改,两者features属性的值是相同的

深入学习jquery源码之继承方案的选择_数组_03

 

create()实现继承

create的第二参数是一个对象,其中的属性如果和person重名,则会覆盖person的属性。

var person={
name:"Tom",
age:23,
job:"厨师"
};
var anotherPerson=Object.create(person,{
name:{
value:"Mike"
}
});
alert(anotherPerson.name);

 

apply()实现属性和方法继承全部继承

apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。

apply(thisArg [,argArray] );                 // 参数数组,argArray

只接收两个参数,其中第二个参数必须是一个数组或者类数组

作用都是将函数绑定到另外一个对象上去运行,内部的this指针,都会被赋值为thisArg,这可实现将函数作为另外一个对象的方法运行的目的

function add(a,b){
return a+b;
}
function sub(a,b){
return a-b;
}
var a1 = add.apply(sub,[4,2]);  //sub调用add的方法
var a2 = sub.apply(add,[4,2]);
alert(a1); //6
alert(a2); //2

/*call的用法*/
var a1 = add.call(sub,4,2);

apply : obj1.fun.apply(obj2,[参数1,参数2....]) 让对象1的方法冒充成对象2的方法。

function person (name) {
this.name=name;//this代表window this那个对象引用,就是那个对象的函数function person()
this.say=function () {
alert(this.name)
}
}

function student () {
window.person.cell(this)//this代表zhangsan
}
var zhangsan=new student ();
zhangsan.name;//张三

function student () {
window.person.apply(this,["zhangsan"])//参数以数组形式传递
}

var zhangsan=new student ();
zhangsan.name;
zhangsan.say();

js实现多态

<script type="text/javascript">
function Animal(name,age){
this.name=name;
this.age=age;
this.shout=function(){
alert("我是:"+this.name+",今年:"+this.age);
};
this.action=function(){
alert("会吃");
};
}

function Dog(name,age){
Animal.apply(this, [name,age]);
}

var jack=new Dog("jack",1);
alert(jack.name);
alert(jack.age);
jack.shout();
jack.action();
</script>

深入学习jquery源码之继承方案的选择_原型链_04

深入学习jquery源码之继承方案的选择_数组_05

深入学习jquery源码之继承方案的选择_原型链_06

深入学习jquery源码之继承方案的选择_父类_07

深入学习jquery源码之继承方案的选择_数组_08

 

 

构造函数call()

call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。

function.call(obj[,arg1[, arg2[, [,.argN]]]]])
  • 调用​​call​​的对象必须是个函数function
  • ​call​​​的第一个参数将会是function改变上下文后指向的对象,如果不传,将会默认是全局对象​​window​
  • 第二个参数开始可以接收任意个参数,这些参数将会作为function的参数传入function
  • 调用​​call​​的方法会立即执行

call : obj1.fun.call(obj2,参数1......).让对象1的方法冒充成对象2的方法。

function person () {
this.name="张三";
this.say=function () {
alert(this.name)
}
}

function student () {
this.name="李四";
}
var ren=new person ();
var zhangsan=new student ();//也有了say方法

ren.say.call(zhangsan)//李四

call的一个作用是可以改变函数运行的作用域

把Person的方法放到Student上执行,原来Student是没有say方法,现在是把Person的say方法放到student上来执行,所以this就指向了student对象

 

构造函数也可以通过子对象向父对象传递参数

function SuperType(name){
this.name=name
}
function SubType(){
SuperType.call(this,"Tom")//或者apply()
}
var instance1=new SubType();
alert(instance1.name);

 

由于可以改变​​this​​的指向,所以也就可以实现对象的继承

function superClass () {
this.a = 1;
this.print = function () {
console.log(this.a);
}
}

function subClass () {
superClass.call(this);
this.print();
}

subClass();
// 1

​subClass​​​通过​​call​​​方法,继承了​​superClass​​​的​​print​​​方法和​​a​​​变量,同时​​subClass​​还可以扩展自己的其他方法

的意思就是使用superClass对象代替this对象,那么subClass中不就有superClass的所有属性和方法了吗,subClass对象就能够直接调用superClass的方法以及属性了

 

异同

相同点

都能够改变方法的执行上下文(执行环境),将一个对象的方法交给另一个对象来执行,并且是立即执行.

一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。

var Pet = {
words : '...',
speak : function (say) {
console.log(say + ''+ this.words)
}
}
Pet.speak('Speak'); // 结果:Speak...

var Dog = {
words:'Wang'
}

//将this的指向改变成了Dog
Pet.speak.call(Dog, 'Speak'); //结果: SpeakWang
---------------------
function Pet(words){
this.words = words;
this.speak = function () {
console.log( this.words)
}
}
function Dog(words){
//Pet.call(this, words); //结果: Wang
Pet.apply(this, arguments); //结果: Wang
}
var dog = new Dog('Wang');
dog.speak();
---------------------

不同点

​call​​方法从第二个参数开始可以接收任意个参数,每个参数会映射到相应位置的func的参数上,可以通过参数名调用,但是如果将所有的参数作为数组传入,它们会作为一个整体映射到func对应的第一个参数上,之后参数都为空

function func (a,b,c) {}

func.call(obj, 1,2,3)
// function接收到的参数实际上是 1,2,3

func.call(obj, [1,2,3])
// function接收到的参数实际上是 [1,2,3],undefined,undefined

​apply​​方法最多只有两个参数,第二个参数接收数组或者类数组,但是都会被转换成类数组传入func中,并且会被映射到func对应的参数上

func.apply(obj, [1,2,3])
// function接收到的参数实际上是 1,2,3

func.apply(obj, {
0: 1,
1: 2,
2: 3,
length: 3
})
// function接收到的参数实际上是 1,2,3

两个方法该如何选择?

跟简单,根据你要传入的参数来做选择,不需要传参或者只有1个参数的时候,用​​call​​​,当要传入多个对象时,用​​apply​

或者,如果需要传入的参数已经是一个数组或者类数组了,就用​​apply​​​,如果还是单独的需要逐个传入的,可以考虑使用​​call​​(如果你不嫌麻烦的话 )

 

 

 

 

 

 

 

标签:jquery,function,name,继承,源码,call,apply,参数,方法
From: https://blog.51cto.com/u_11837698/6081930

相关文章

  • 深入学习jquery源码之extend()
    jQuery.extend([deep],target,object1,[objectN])概述:用一个或多个其他对象来扩展一个对象,返回被扩展的对象。如果不指定target,则给jQuery命名空间本身进行扩展。这有助......
  • 深入学习jquery源码之上传附件插件的实现
    深入学习jquery源码之上传附件插件的实现/***上传附件通用JS(基于layerUI)*/;(function($){vardefaults={url:"/attach/upload",fieldCode:"ab......
  • 深入学习jquery源码之attr()与removeAttr()
    深入学习jquery源码之attr()与removeAttr()attr(name|properties|key,value|fn)概述设置或返回被选元素的属性值。参数name String属性名称properties Map作为属性的“名/......
  • 深入学习jquery源码之jQuery的构造函数与实例化
    深入学习jquery源码之jQuery的构造函数与实例化创建jQuery对象的整个流程如下:1、调用$()方法;2、调用jQuery.prototype.init()构造函数;3、根据选择器不同返回不同的jQuery对......
  • 深入学习jquery源码之queue()与dequeue()
    深入学习jquery源码之queue()与dequeue()queue(element,[queueName])概述显示或操作在匹配元素上执行的函数队列参数element,[queueName] Element,Stringelement:检查附加......
  • 深入学习jquery源码之序列化表单
    深入学习jquery源码之序列化表单serialize()概述序列表表格内容为字符串。序列表表格内容为字符串,用于Ajax请求。<pid="results"><b>Results:</b></p><form><select......
  • 深入学习jquery源码之jQuery的核心参数
    深入学习jquery源码之jQuery的核心参数jQuery([selector,[context]])概述这个函数接收一个包含CSS选择器的字符串,然后用这个字符串去匹配一组元素。jQuery的核心功能都是......
  • 深入学习jquery源码之is()与not()
    深入学习jquery源码之is()与not()is(expr|obj|ele|fn)概述根据选择器、DOM元素或jQuery对象来检测匹配元素集合,如果其中至少有一个元素符合这个给定的表达式就返回true。......
  • 深入学习jquery源码之arguments和callee
    深入学习jquery源码之argumentsjs中的函数其实是对象,函数名是对Function对象的引用,arguments这个对象不能显式创建,arguments对象只有函数开始时才可用。每创建一个函数,该......
  • 深入学习jquery源码之filter()与find()
    深入学习jquery源码之filter()与find()filter(expr|obj|ele|fn)概述筛选出与指定表达式匹配的元素集合。这个方法用于缩小匹配的范围。用逗号分隔多个表达式参数expr Strin......