`

js两种定义函数、继承方式及区别

 
阅读更多
一:js两种定义函数的方式及区别

1:函数声明:
function  sayA() {   alert("i am A");  }
2:函数表达式:
var sayB = function() {   alert("i am B");  }
区别:code
前者会在代码执行之前提前加载到作用域中,后者则是在代码执行到那一行的时候才会有定义


二:js两种继承方式及区别
对象冒充
临时属性
call()
apply()
原型链 code
继承应选哪种 code

三:实例
js两种定义函数的方式:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>js两种定义函数的方式</title>
<script language="javascript">
    say();
    var say =function(){
        alert("567");
    }
    function say(){
        alert("123");
    } 
</script>
</head>
<body>
</body>
</html>
//在javascript函数体内(执行作用域)声明的变量,无论在函数体何处声明,它将都会被提升到函数的顶部,我们称这种现象为变量提升。
函数呢,它也有这种特性,即无论在函数体何处声明另一个函数,它将都会被提升到函数的顶部。
只是采用函数表达式和函数声明所体现的函数提升的内容是有差别的:函数表达式和变量提升类似,只会提升函数的变量,不提升函数的定义;
而函数声明提升时,不仅仅会提升函数的声明,函数的定义也会被提升
对象冒充:临时属性

function Person(name){
     this.name = name;
     this.say = function(){
        alert('My name is '+this.name);
     }
}
function Student(name,id){
    this.temp = Person;
    this.temp(name);
    delete this.temp;
    this.id = id;
    this.showId = function(){
       alert('Good morning,Sir,My student number is '+this.id);
    }
}
var simon = new Student('Simon',9527);
simon.say(); //my name id simon
simon.showId(); //Good morning,Sir,My work number is 9527
对象冒充:apply()/call():

function Person(name){
    this.name = name;
    this.say = function(){
      alert('My name is '+this.name);
    }
}
function Student(name,id){
    Person.call(this,name); //apply():Person.apply(this,new Array(name));
     this.id = id;
     this.showId = function(){
        alert('Good morning,Sir,My student number is '+this.id);
     }
}
var simon = new Student('Simon',9527);
simon.say();
simon.showId();
//apply(this,arguments):方法能劫持另外一个对象的方法,继承另外一个对象的属性.
                        arguments:是一个数组,new Array(name,age)等
//call(id,name,age)
//什么情况下用apply,什么情况下用call 
在给对象参数的情况下,如果参数的形式是数组的时候,
比如apply示例里面传递了参数arguments,这个参数是数组类型,
并且在调用Person的时候参数的列表是对应一致的(也就是Person
和Student的参数列表前两位是一致的) 就可以采用 apply ,
如果我的Person的参数列表是这样的(age,name),而Student
的参数列表是(name,age,grade),这样就可以用call来实现了,
也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade)); 
//apply和call中的参数顺序以父类为准。
原型链继承:new

var Shape = function(width, height) {
    this.width = width;
    this.height = height;
};
Shape.prototype.area = function() {
    return this.width * this.height
};
var shape = new Shape(20, 30);
shape.area();
> 600
原型链继承:无new

function Shape(width, height) {
    if (!(this instanceof Shape)) {
        return new Shape(width, height);
    }
    this.width = width;
    this.height = height;
    return this;
}  
Shape.prototype.area = function() {
    return this.width * this.height
};
var shape = Shape(20, 30);
console.log(shape.area());


选择最优继承方式:

1:在OO概念中,new实例化后,对象就在堆内存中形成了自己的空间, 值得注意的是,这个代码段。而成员方法就是存在这个代码段的, 并且方法是共用的。问题就在这里,通过对象冒充方式继承时, 所有的成员方法都是指向this的,也就是说new之后,每个实例将 都会拥有这个成员方法,并不是共用的,这就造成了大量的内存浪费。 并且通过对象冒充的方式,无法继承通过prototype方式定义的变量和方法,如以下代码将会出错:

function Person(name){
    this.name = name;
    this.say = function(){
       alert('My name is '+this.name);
    }
}
Person.prototype.age = 20;
Person.prototype.sayAge = function(){alert('My age is '+this.age)};
function Student(name,id){
     Person.apply(this,new Array(name));
         this.id = id;
         this.showId = function(){
         alert('Good morning,Sir,My student number is '+this.id);
     }
}

var simon = new Student('Simon',9527);
simon.sayAge(); //提示TypeError: simon.sayAge is not a function  
2:原型链方式继承,就是实例化子类时不能将参数传给父类,这个例子中function Person()没有参数。

function Person(name){
    this.name = name;
}
Person.prototype.say = function(){
    alert('My name is '+this.name);
}
function Student(name,id){
    this.id = id;
    this.showId = function(){
       alert('Good morning,Sir,My student number is '+this.id);
}
}
Student.prototype = new Person();
//此处无法进行传值,this.name或者name都不行,
//直接写Student.prototype = new Person('wood')是可以的,
//但是这样的话simon.say()就变成了My name is wood
var simon = new Student("Simon",9527);
simon.say();  //弹出 My name is undefined
simon.showId();
结论:

成员变量采用对象冒充方式,成员方法采用原型链方式

function Person(name){
    this.name = name;
}
Person.prototype.say = function(){
    alert('My name is '+this.name);
}
function Student(name,id){
    Person.call(this,name);
    this.id = id;
}
Student.prototype = new Person();
//此处注意一个细节,showId不能写在Student.prototype = new Person();前面
Student.prototype.showId = function(){
    alert('Good morning,Sir,My student number is '+this.id);
}
var simon = new Student("Simon",9527);
simon.say();
simon.showId();

转自:http://www.cnblogs.com/m-xy/p/3924355.html

js中的变量提升

1 var v='Hello World';
2 (function(){
3 alert(v);
4 var v='I love you';
5 })() 


会出现alert出来的是undefined,原因是因为在函数域里定义一个和外部变量一样名称的变量时,变量的声明会提升至第一句,赋值则不会变。所以上述语句其实是这样执行的

var v='Hello World';
(function(){
var v;
alert(v);
v='I love you';
})() 


转自:http://www.cnblogs.com/yamadie/p/3160204.html
分享到:
评论

相关推荐

    JS 四种函数调用模式

    在 JS 中,有四种主要的函数调用模式,分别是:普通函数调用、方法调用、构造函数调用和apply/call调用。下面我们将详细探讨这些调用模式。 1. **普通函数调用**: 这是最常见的情况,函数作为一个独立的实体被执行...

    JavaScript定义类或函数的几种方式小结

    混合构造函数/原型模式结合了构造函数和原型两种方式的优点。通过构造函数定义对象的属性,通过原型定义对象的方法。这样,每个对象的属性仍然是唯一的,而方法则可以通过原型链被所有对象共享。混合模式的代码示例...

    学习javascript面向对象 javascript实现继承的方式

    在JavaScript中,实现继承有多种方式,每种方式都有其特点、优势和不足。本文将详细介绍六种实现JavaScript继承的方法。 1. 原型链继承 原型链继承是通过改变子类型的原型对象来实现继承的。子类型构造函数的原型被...

    javascript指南和函数式编程

    本指南将深入探讨JavaScript的高效编程和函数式编程这两个重要主题,帮助开发者提升技能,实现更优雅、更可维护的代码。 《Effective JavaScript(中文版).pdf》这本书是JavaScript编程的经典之作,它包含了68个具体...

    JS封装和继承-入门级

    1. **作用域**:JavaScript有两种作用域,全局作用域和局部作用域。通过在函数内部定义变量,我们可以创建局部作用域,限制变量的访问范围。 2. **闭包**:闭包允许函数访问并操作其词法作用域内的变量,即使该函数...

    js原型继承的两种方法对比介绍.docx

    ### JS原型继承的两种方法对比介绍 #### 一、引言 在JavaScript中,对象间的继承机制主要依赖于原型链。原型链的概念使得JavaScript能够实现动态面向对象编程,并且提供了非常灵活的对象创建与继承的方式。在实际...

    JS箭头函数和常规函数之间的区别实例分析【 5 个区别】

    在JavaScript编程中,函数是核心组成部分,而箭头函数和常规函数是两种常见的函数定义方式。它们之间存在显著的区别,这些差异在实际开发中具有重要的意义。以下是五个关键区别以及相关实例分析: 1. **this值的...

    javascript函数速查

    JavaScript有两种作用域:全局作用域和函数作用域。在函数内部声明的变量仅在该函数内部可见。ES6引入了块级作用域,通过let和const关键字实现,但函数作用域仍然独立于块级作用域。 七、闭包 闭包是指函数可以访问...

    javascript 构造函数方式定义对象

    在示例中,提供了两种方式定义比较函数: - 显式命名函数: ```javascript array.sort(compare); function compare(num1, num2) { // 比较逻辑 } ``` - 匿名函数: ```javascript array.sort(function(num...

    浅谈js对象的创建和对6种继承模式的理解和遐想

    3. 组合继承:组合继承结合了原型链和借用构造函数两种方式,是JavaScript中最常用的继承方式。它使用原型链继承原型上的属性和方法,又通过借用构造函数继承实例属性,这样既保证了功能的完整,又能实现属性和方法...

    javascript用函数实现继承详解javascript技巧docx.docx

    在JavaScript中,可以使用多种方式来实现继承,其中之一就是通过函数来模拟继承。本文将详细介绍如何利用函数实现JavaScript的继承,并结合属性特性和描述符来深入理解这一过程。 首先,我们要了解JavaScript中的...

    JavaScript中的普通函数和箭头函数的区别和用法详解.docx

    JavaScript中的函数有两种主要类型:普通函数(也称为传统函数或函数表达式)和箭头函数。这两种函数在语法和行为上都有所不同,对于理解和编写JavaScript代码至关重要。 ### 普通函数 #### 1. 定义 普通函数通过`...

    javascript的函数

    另一种定义函数的方法是通过函数表达式,即将函数赋值给一个变量: ```javascript var functionName = function([parameters]){ functionBody; }; ``` 这种情况下,函数可以是匿名的,也可以带有名称。如果带...

    CSDN官方js函数大全

    函数声明和函数表达式是两种创建函数的方式。此外,还有箭头函数的简洁写法。 4. **对象**: JavaScript的对象是键值对的集合,可以使用字面量语法或构造函数创建。对象的方法和属性可以通过点号或方括号操作符...

    基于JavaScript实现继承机制之构造函数+原型链混合方式的使用详解

    首先来分析构造函数和原型链两种实现继承方式的缺陷: 构造函数(对象冒充)的主要问题是必须使用构造函数方式,且无法继承通过原型定义的方法,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数...

    关于js继承笔记.doc

    这里我们主要探讨三种实现JavaScript继承的方式:原型链继承、构造函数继承和组合继承。 首先,原型链继承是JavaScript最常用的继承方式。在JavaScript中,每个函数都有一个prototype属性,这个属性是一个对象,它...

    JavaScript中函数对象调用模式总结

    JavaScript中的函数对象调用模式是编程中至关重要的概念,它涉及到函数作为一等公民、作用域、闭包、原型链等多个核心知识点。这篇博客通过深入分析JavaScript中的函数调用模式,帮助开发者更好地理解和掌握这些概念...

    javascript的函数 入门详解

    这两种定义方式在功能上是等价的,都是创建一个可调用的函数对象。 2. 函数作为对象 - JavaScript中的函数是对象,因此它们具有对象的属性和方法。例如,可以像普通对象那样为函数添加属性,如`test.name = '...

    js函数扩展

    7. **默认参数和剩余参数**:默认参数允许我们在定义函数时为参数提供默认值,而剩余参数(`...rest`)则能捕获未指定位置的剩余参数,方便处理不定数量的输入。 8. **异步函数**:随着Promise和async/await的引入...

    JS继承笔记.7z

    - 寄生组合式继承解决了构造函数继承的缺点,通过在子类构造函数内部调用父类构造函数,并利用工厂函数创建实例,避免了属性的重复。 6. 寄生继承: 主要用于改善对象的创建,通过一个辅助函数创建原始对象的副本...

Global site tag (gtag.js) - Google Analytics