你真的了解变量吗?

Posted _小许_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你真的了解变量吗?相关的知识,希望对你有一定的参考价值。

变量是编程语言中最基本的术语,用来代指计算机中存放的可变数据——如整数、小数、字符或被调用的一片内存空间。

变量可以保存不同的变量类型,比如整型、布尔型、对象、数组等等,每一个变量在内存中对应着一个内存地址,但是如果一个变量保存一个原始数据类型(整型、布尔型、字符串)则该变量的值是保存在栈内存中,而相对于那些较复杂的数据类型(数组、对象)则是在栈中只存储了一个固定长度的地址,这个地址指向堆内存中的值。这是由于栈和堆的两种数据结构的性质决定的。

对变量的使用一般包括变量的定义,变量的调用,变量的值传递,变量的销毁与内存释放。

变量可以时任何数据类型,数字,字符字符串,方法,对象等。变量的定义归结于不同语言的语法,如:

//java

//简单数据类型
String name = "_小许_";
String name = null;

int age = 21;
boolean flag = true;

//复杂数据类型对象
class Person
	String name;
	Integer age;


Person person1 = new Person();


# python
a = 10
b = "_小许_"

# 函数变量
def showName:
	print("_小许_")

# 对象变量
class Person:
    def __init__():
        print("_小许_")

Person.__init__()
// go
var x int =10
y := "_小许_"
const name = "_小许_"

//结构体变量
type Person struct 
	name string
	age int



变量的销毁都有语言的编译器或者解析器的GC来完成。

变量的传递是变量的核心,变量定义出来就是为了传递到不同的方法中实现不同操作,最终的得到用户需要的结果。

变量的传递包括值传递和引用传递,这也是和语言的特性息息相关,值传递是浅传递,引用传递是深传递。前者是简单的值拷贝,后者是内存地址的在此引用,一般通过修改指针变量来完成。

变量传递的途径,变量一般包含局部变量和全局变量,变量最终都通过IO输出并在内存中被销毁,因此变量只有在编译时在有意义。

笼统的说,在程序中对变量实现附加操作的主体就是方法,算数运算,逻辑运算等这些一般也依附于方法。无论是面向对象语言还是面向过程语言。

例如,在面向过程语言c语言中:

#include <stdio.h>
int sum()
    int i, sum=0;
    for(i=1; i<=100; i++)
        sum+=i;
    
    return sum;

int main()
    int a = sum();
    printf("The sum is %d\\n", a);
    return 0;

//java

public class Main 

    public static void main(String[] args) 
	// write your code here
        NumUtil un = new NumUtil();
        int sum = un.sum();
        System.out.println(sum);
    



class NumUtil
    private int tmp = 0;
    public int sum()
        for (int i =0 ;i<=100;i++)
            tmp = tmp + 1;
        
        return tmp;
    


在上面的传递方式中,方法中都有一个默认值,作为初始值,也可以自定义初始值:

public class Main 

    public static void main(String[] args) 
	// write your code here
        NumUtil un = new NumUtil();
        int sum = un.sum();
        System.out.println(sum);
    



class NumUtil
    private int tmp = 0;
    public int sum(int a)
    	tmp = a;
        for (int i =0 ;i<=100;i++)
            tmp = tmp + 1;
        
        return tmp;
    

sum(int a)中传递了一个名为a大的变量,在其数据类型是int,那么在调用该函数时传递的参数就必须时int类型。

不同语言的规范不一样,定义的规则也一样,传递的规则也是。例如,在C语言中int i;就是表示定义了一个int内置类型的变量,名称为i;在Java中String name就是定义了一个名为name的String类型;这些是强类型语言的定义,像js,python等弱类型语言的定义方式又不一样a = 1是python定义变量的方式,a可以是是任意类型,最终类型又开发者赋予的值类决定。在js中提供了val,let,const定义局部和全局变量,且也是自动类型推断。在许多后来的语言中都有局部变量和全局变量的关键字定义,例如在scala中,var a :String = "_小许_"等等。

如下为常见的变量定义:

//c语言变量定义
int i, sum=0;

//变量传递


//java
String name = "";
# python
a = 0;
//go
a := 0

函数的定义在强类型语言中必须要声明类型,如在函数定定义局部变量,在函数的参数中定义变量,而在若类型的语言中,定义变量不需要声明类型,但是必须要有初始值,由编译器或者解析器推断类型。

有些语言如Scala提供了var,val等一些关键字,Go的var,const关键字来区别于局部变量和常量,这些只在方法体内生效。(方法的参数是方法的一部分,不能使用这些关键字)。

总的来说,函数的变量可以分为:局部变量,全局变量,形式变量。

  • 函数内定义的变量称为局部变量
  • 函数外定义的变量称为全局变量
  • 函数定义中的变量称为形式参数

在函数体内声明的变量称之为局部变量,它们的作用域只在函数体内,函数的参数和返回值变量都属于局部变量。局部变量不是一直存在的,它只在定义它的函数被调用后存在,函数调用结束后这个局部变量就会被销毁。

//go
func addNum(a int,b int) int
	y := 3*a+4*b;
	return y

//java
public class Util
	public int addNum(int a,int b)
		int y = 3*a + 4*b;
		return y;
    

y均为局部变量。

在函数体外声明的变量称之为全局变量,全局变量只需要在一个源文件中定义,就可以在所有源文件中使用。有些语言变量必须定义在类中如Java,有的语言可以定义在源文件中,如Go在外部包中使用全局变量的首字母必须大写。

//go语言
package main
import "fmt"
//声明全局变量
var c int
func main() 
    //声明局部变量
    var a, b int
    //初始化参数
    a = 3
    b = 4
    c = a + b
    fmt.Printf("a = %d, b = %d, c = %d\\n", a, b, c)

//java
public class Person
	private int id;
	private String name;
	private Double price;

在定义函数时函数名后面括号中的变量叫做形式参数(简称形参)。形式参数只在函数调用时才会生效,函数调用结束后就会被销毁,在函数未被调用时,函数的形参并不占用实际的存储单元,也没有实际值。

//go
func operation(n int, m int) (int, int, int, int) 
	return n + m, n - m, n * m, n / m

//java
public class Person
	private int id;
	private String name;
	private Double price;
	
	public void setId(int id)
		this.id = id;
	
	public int getId()
		return this.id;
	

	public void setName(String name)
		this.name = name;
	
	public int getName()
		return this.name;
	

	public void setPrice(Double price)
		this.price = price;
	
	public Double getPrice()
		return this.price;
	

你真的了解JavaScript吗

第一题

  

  其实就是变量提升的概念

  var a;

  if(!(\'a\' in window)){

    a = 1;

  }

  console.log(a);

第二题

  

  这里就是函数声明会覆盖变量声明了; 即使函数声明写在变量声明的后面。也会覆盖,但是函数表达式不会覆盖。

第三题

  

  函数上下文中的变量对象一节就可以清楚地知道,活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性的值是Arguments对象:

  Arguments对象是活动对象的一个属性,它包括如下属性:

  1. callee — 指向当前函数的引用  arguments.callee.length 就是形参个数 也可以使用函数名字.length; 其实 funName.length === arguments.callee.length;
  2. length — 真正传递的参数个数
  3. properties-indexes (字符串类型的整数) 属性的值就是函数的参数值(按参数列表从左到右排列)。 properties-indexes内部元素的个数等于arguments.length. properties-indexes 的值和实际传递进来的参数之间是共享的。

  这个共享其实不是真正的共享一个内存地址,而是2个不同的内存地址,使用JavaScript引擎来保证2个值是随时一样的,当然这也有一个前提,那就是这个索引值要小于你传入的参数个数,也就是说如果你只传入2个参数,而还继续使用arguments[2]赋值的话,就会不一致,例如:

第四题

  

  根据ECMAScript262规范规定:如果第一个参数传入的对象调用者是null或者undefined的话,call方法将把全局对象(也就是window)作为this的值。所以,不管你什么时候传入null,其this都是全局对象window。如果是alert(this); 就是 ‘[object Window]’;

 

以上是关于你真的了解变量吗?的主要内容,如果未能解决你的问题,请参考以下文章

C语言变量应该怎样使用,你真的了解了吗!

Python是什么?你真的了解Python吗?

你真的了解console吗?

json,你真的足够了解吗?

你真的了解“SQL”吗?《SQL优化最佳实践》作者带你重新了解SQL

Java开发篇——设计模式单例模式你真的了解吗?(下)