精华内容
下载资源
问答
  • C# 函数式编程初探

    2020-12-13 22:55:55
    (二)C#中有哪些常见的函数式方法 LINQ的Where和OrderBy函数对列表进行过滤或排序不会影响原始列表; Sort函数对列表排序会影响原始列表。 var nums = Range(-10000,20001).Reverse().ToList();//[10000,9999,..,-...

    (一)什么是函数式编程
    函数式编程(FC)是以函数作为第一类值,避免状态突变的编程风格。
    状态突变:存储在寄存器的值就地更新。
    (二)C#中有哪些常见的函数式方法
    LINQ的Where和OrderBy函数对列表进行过滤或排序不会影响原始列表;
    Sort函数对列表排序会影响原始列表。

    var nums = Range(-10000,20001).Reverse().ToList();//[10000,9999,..,-9999,-10000]
    Action task1 = ()=> WriteLine(nums.Sum());
    Action task2 = ()=> {nums.Sort();WriteLine(nums.Sum())};
    Parallel.Invoke(task1,task2);
    // prints : 随机数;
    // prints : 0;
    
    Action task3 = ()=> WriteLine(nums.OrderBy(x=>x).Sum());
    Parallel.Invoke(task1,task3);
    //prints : 0;
    //prints:0
    

    (三) C# 6和C# 7 中的函数式特性

    • 使用using static 导入静态成员,使用静态函数时,无需使用静态类名
    using static System.Math;
    public double Circumference => PI * 2;
    
    • 具有只读的自动属性
    public class A
    {
    	public A (double readOnlyField) => ReadOnlyField = readOnlyField;
    	public double ReadOnlyField {get;} // 由于ReadOnlyField只有在构造函数中被赋值,一旦被创建,便不可被修改,属于不可变类型,因此编译器会隐式声明为readonly。内联函数中被赋值同理。
    }
    
    • 具有表达式体式的成员
    public double Circumference => PI * 2
    
    • 局部函数
      通过在方法作用域内声明局部函数,明确局部函数只能从一个位置被调用
    get
    {
    	double Square(double d)=>Pow(d,2);
    	return PI * Square(2);
    }
    
    • 元组语法
      元组在FP中的作用更倾向于将任务分解为非常小的函数,通常将元组类型的输出 当作另一个函数的 输入
    public (double a,double b) Stats => (A,B);
    
    展开全文
  • java基础相关 JDK8有哪些了解 ...JVM有哪些了解 ...String,StringBuffer,StringBuilder三者有哪些区别 ...构造函数,重载,重写 ...List,Set,Map三者集合和接口有哪些不同,接口实现类...线程的状态,继承方式,启动...

    java基础相关

    • JDK8有哪些了解

      • 新增语法:lambda表达式(也叫闭包): Lambda允许把函数作为一个方法的参数(函数作为参数传递进方法中),或者把代码看成数据。并且使用lambda可以少些一些代码。
      • 接口的新特性:Java 8用默认方法与静态方法这两个新概念来扩展接口的声明,默认方法与传统的接口又有些不一样,它允许在已有的接口中添加新方法,而同时又保持了与旧版本代码的兼容性,且默认方法与抽象方法不同之处在于抽象方法必须要求实现,但是默认方法则没有这个要求。相反,每个接口都必须提供一个所谓的默认实现,这样所有的接口实现者将会默认继承它,这个默认实现一般为Defaulable。
      • 注解特性:@Repeatable注解定义重复注解,允许在同一个地方多次使用同一个注解。
      • 方法引用:可以直接引用现存的方法、Java类的构造方法或者实例对象。与lambda联合使用,使得java类的构造方法看起来紧凑而简洁,没有很多复杂的模板代码。
      • 更好的类型推测机制
    • String,StringBuffer,StringBuilder三者有哪些区别

      String是不可变对象,StringBuffer和StringBuilder是可变对象。
      String类型每次改变都等于是又生成一个新的String,所以在多次遍历String常量的时候且数据有很多的时候,就比较耗性能,耗内存。
      StringBuffer是线程安全的,他的对象被修改时不会产生新的对象,所以在遍历多个数据时他会比String快得多。并且源码中所有写操作都被synchronized修饰了,所以所有修改操作都是串行的。
      StringBuilder在修饰的对象在修改时也不会产生新的对象。但他是非线程安全的。所以在速度上会比StringBuffer更快。他的源码中的所有写操作则没有使用synchronized进行修饰,也不包含其他串行化修改的算法。

    • 重载,重写

      重写:重写一般是子类去继承父类的方法,方法名和参数都相同,也可以理解为对父类方法或函数重新定义。参数列表必须完全与被重写的方法相同,否则不能称其为重写;返回类型必须一直与被重写的方法相同,否则不能称其为重写。重写是父类与子类之间多态性的表现,在运行时起作用(动态多态性,譬如实现动态绑定)
      重载:重载可以理解以同一方式处理不同类型参数的手段,比如为同一个类中,A,B,C三个方法的方法名一样,参数不一样。重载规则必须具有不同的参数列表; 可以有不同的返回类型;可以有不同的访问修饰符;可以抛出不同的异常。重载是一个类中多态性的表现,在编译时起作用(静态多态性,譬如实现静态绑定)

    • List,Set,Map三者集合和接口有哪些不同,接口实现类分别有哪些

      List,Set继承了Collection接口,Map没有继承Collection
      List中的元素可以重复,有序,允许为空;ArrayList和LinkedList:ArrayList是动态数组的数据结构,查改快;LinkedList是链表的数据结构,增删快。
      Set不可以重复,无序,最多只允许一个空值;
      Map的key可以不重复,value可以重复,无序(TreeMap会根据键对其中的元素进行升序排序),key最多只允许一直空值,value可以有多个空值。
      HashMap和HashTable:
      hashMap非线程安全;hashTable线程安全
      在多个线程访问HashTable时,不需要自己为它的方法实现同步,而HashMap就必须为之提供外同步。
      HashMap允许将null作为一个entry的key或者value,而HashTable不允许。

    • int和Integer有哪些区别

      int是一种基本数据类型,integer是int的包装类
      integer必须实例化后才能使用,int不需要
      integer默认值是null,int是0
      integer的缓存范围是-127——128.这是Java为了节省内存,IntegerCache类中固定的。int的取值范围正负2的32次方。
      自动拆箱装箱JDK5以上,系统会自动基于数据类型和对应的包装类进行转换。装箱是基本类型转换为包装类(int转integer),拆箱相反。

    • 接口和抽象类有哪些异同

      相同点
      (1) 都可以被继承。(2) 都不能被实例化。(3) 都可以包含方法声明。(4) 派生类必须实现未实现的方法
      不同点
      (1) 抽象类可以有构造方法,接口中不能有构造方法。(2) 抽象类中可以有普通成员变量,接口中没有普通成员变量。(3) 抽象类中可以包含静态方法,接口中不能包含静态方法。(4) 一个类可以实现多个接口,但只能继承一个抽象类。(5) 如果抽象类实现接口,则可以把接口中方法映射到抽象类中作为抽象方法而不必实现,而在抽 象类的子类中实现接口中方法

    • equals和==有什么区别

      equals比较两个值是否相等,只用于String;==比较两个对象或者说地址是否相等。例如两个new出来的String,equals返回true,=返回false。

    • 进程和线程的区别。线程的状态,继承方式,启动方式有哪些,以及wait和sleep之间有哪些区别

      一个进程可以包含多个线程,进程有多线程和单线程

      • 继承线程的方式:1继承Thead类;2实现Runnable接口。
        如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。而Runable接口的优势有:
        1):适合多个相同的程序代码的线程去处理同一个资源
        2):可以避免java中的单继承的限制(不能访问父类的私有成员?)
        3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立
        4):线程池只能放入实现Runable或callable类线程,不能直接放入继承Thread的类
      • run()和start():真正启动线程的方法就是start()方法。run()方法只不过是一个普通的方法,如果直接调用run()方法,还是在主线程顺序执行。
      • wait 和 sleep 都能将线程状态变成等待状态,除了这点相同点,其它基本都不同。比如:
           1、wait()是定义在Object 类中的,是一个final修饰的非静态方法;而sleep是被定义在Thread类中的,是一个static修饰的静态方法;
           2、wait()必须用于同步环境,如synchronized方法或者同步代码块、生产-消费者队列,通常配合notify()方法使用,wait 让生产者线程等待,notify唤醒消费者线程,通知队列非空;而sleep()没有这个限制。
           3、调用wait()时会释放当前持有的锁,而sleep()不会释放任何锁。
      • 多线程应用场景及优缺点
        应用场景:1、定时向大量用户发送邮件或短信时,所有的发送请求都是多线程实现的。2、短信和邮件接口在注册时比较耗时,一般也是多线程实现的,这样可以使用户体验比较好。3如果需要写一个电商网站,那么用户量很大的时候(比如双11)就是多线程的最好的体现。4像在我们自己项目中从Kafka中抓取数据时,有时候数据太多,抓取不过来,这时候就需要用到多线程。
        优点:1、响应快,可以把响应时间长的线程放在后台处理;2、用户体现会更好;3、效率更高(因为CPU使用率高了);4、解决数据量特别大的场景(双十一商场,12306等)。
        缺点:1、因为操作系统需要在每个线程之间来回切换,所以线程越多,越影响性能。2、占用内存,每个线程JVM都要为他创建一个栈空间,所以线程越多越耗内存。3、每个线程终止的时候都要考虑对程序的影响。4、模型数据是在多个线程中共享的,可能会造成死锁(比如两个线程相互等待)。
    • Synchronized和lock的区别

      1、Synchronized是java的内置关键字;lock则是一个Java接口。
      2、Synchronized无法判断锁的状态;lock可以。
      3、Synchronized可以自动释放锁(当一个线程执行完毕后或者正在执行的过程中出现异常都会释放锁);lock不会自动释放锁(需要手动的在finally中用unlock()方法释放锁,否则容易造成线程死锁)。
      4、Synchronized的两个线程,如果一个线程发生阻塞,其他线程就只能一直等下去;lock则不用一直等,如果尝试获取不到锁(使用trylock()方法),线程就会自动结束。
      5、Synchonized适合少量同步数据,lock适合大量同步数据。Lock的实现类ReentrantReadWriteLock提供了readLock()和writeLock()用来获取读锁和写锁的两个方法,这样多个线程可以进行同时读操作。

    • session和cookie的区别

      cookie和session都是会话计数。不同之处有:
      1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
      2、cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
      3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
      4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
      5、可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。

    • servlet生命周期

      分为4步:1、servlet容器先加载并实例化servlet。2、调用init()方法对servlet进行初始化(init方法只能调用一次)。3、再用service()方法对请求进行处理。4、最后用destory()方法终止服务。

    • 序列化和反序列化 以及 输入流和输出流

      序列化就是将内存中的对象转换为字节序列,方便持久化到磁盘或者网络传输。也可以理解为将对象写入磁盘。一般用输出流ObjectOutputStream实现。如果某个变量不想被序列化,可在该变量前加transient。
      反序列化相反,就是将字节序列转换为内存中的对象。一般用输入流ObjectInputStream实现。
      Serializable接口作用,缓存将对象写入硬盘,就必须序列化。Java.io.Serializable接口时刻序列化的,没有这个接口就不能进行序列化或者反序列化。这个序列化接口没有任何方法。

    • 设计模式

    六种设计模式:单例模式、工厂模式、观察者模式、迭代器模式、代理模式、适配器模式

    • 单例模式:
         饿汉式(线程安全):
        		public class Singleton1 {
           		 	// 指向自己实例的私有静态引用,主动创建
            		private static Singleton1 singleton1 = new Singleton1();
            		// 私有的构造方法
            		private Singleton1(){}
            		// 以自己实例为返回值的静态的公有方法,静态工厂方法
          	      public static Singleton1 getSingleton1(){
               		 return singleton1;
           	 		}
        		}
        懒汉式(同步延迟加载 — synchronized方法):
        		public class Singleton2 {
            		// 指向自己实例的私有静态引用
           			private static Singleton2 singleton2;
            		// 私有的构造方法
            		private Singleton2(){}
            		// 以自己实例为返回值的静态的公有方法,静态工厂方法(如果多线程下
            		线程安全的懒汉式则需要再static和Singleton2中间加入‘synchronized’即可)
            		public static Singleton2 getSingleton2(){
                		// 被动创建,在真正需要使用时才去创建
               	 	if (singleton2 == null) {
                    		singleton2 = new Singleton2();
                		}
               	 	return singleton2;
            		}
            	}	
        枚举:
        		public enmu Singleton {
        			INSTANCE
        			public void angMethod(){
        			}
        		}
      

    Spring、Springboot、SpringMVC等框架相关(我写的都是常见的,这些其实只要把文档看熟了,理解透了,面试就迎刃而解了)

    • Spring

      Spring是一个轻量级的IOC和AOP容器框架。Spring Bean的注入方式:构造器注入,Setter注入和注解注入。三种配置方式:基于XML配置,基于Java配置,基于注解配置。如果结合 SpringBoot的话,XML很多就不需要进行配置了。
      SpringIOC:IOC(控制反转),他其实是一个设计思想,原本需要手动创建对象,ioc直接交与spring框架来管理。Ioc也可以看作是一个载体,他就是一个Map,在Map中存放各种对象。并且他还很大程度上的简化开发,把应用从复杂的依赖中解放出来。需要创建对象的时候,只需要配置好配置文件和注解就行了,其他的不用考虑,这样一来就大大增加了项目的可维护性且简化了开发难度。
      SpringAOP:Aop(面向切面编程),能够将一些与业务无关,却与业务模块共同调用的逻辑或责任封装起来(比如事务处理,日志管理或权限控制等等)。这样便于减少系统的重复代码,降低模块间的耦合度,并有利于以后对代码的扩展和维护。并且也可以将一些通用的功能给抽象出来,然后有需要的地方直接调用即可。这样对开发者来讲就可以大大减少工作量,也提高了代码的可扩展性。 另,Aop是基于动态代理的。Spring Aop 和 AspectJ的区别:AOP是运行时增强,AspectJ是编译时增强。AOP是基于代理,而AspectJ是基于字节码操作。所以AspectJ就相对于AOP更强大一点,当然了,AspectJ也比AOP复杂得多。所以说,如果是切面比较多的话,用AspectJ比AOP快得多,而切面比较少的时候,AOP就比较合适一点了。
    • SpringMVC

      Spring MVC是一个基于Java的实现了MVC设计模式的轻量级Web框架,通过分离Model,View和Controller,把整个负责的Web应用分为几部分进行开发,这样以来变成逻辑就变得非常清晰了。他的核心就是DispatcherServlet和HandlerMapping。
      流程:首先客户发送请求到DispatcherServlet,前端控制器请求HandlerMapping,HandlerMapping向前端控制器发送Handler,DispatcherServlet根据请求和Handler找到对应的Controller,Controller中执行完逻辑代码后返回一个Model,前端控制器接收到这个ModelAndView后请求视图解析器去解析,视图解析器解析完成后向前端控制器返回一个View,前端控制器再进行渲染,最后响应结果。
    • Springboot

      Spring Boot可以轻松创建独立的,生产级的基于Spring的应用程序。配置文件可以是两种类型:properties(app.user.name=…)和yml(app: 换行 user: 换行 name:…)。
      @SpringBootApplication是Spring Boot的核心注解,它是一个组合注解:包括了@Configuration,@EnableAutoConfiguration,@ComponentScan注解,其中@SpringBootConfiguration就是@Configuration配置类注解,@EnableAutoConfiguration是根据类路径配置的jar包依赖开自动配置的注解。Springboot兼容老spring项目,可以使用@ImportResource注解导入老spring项目配置文件,该注解主要用来加载配置。
      注解:
      @Controller 处理http请求
      @RestController 是一个结合了 @ResponseBody 和 @Controller 的注解
      @Component: 注解在类上,表示通用bean
      @Responsebody 注解表示该方法的返回的结果直接写入 HTTP 响应正文(ResponseBody)中,一般在异步获取数据时使用,通常是在使用 @RequestMapping 后,返回值通常解析为跳转路径,加上@Responsebody 后返回结果不会被解析为跳转路径,而是直接写入HTTP 响应正文中。

    Mysql面试相关:

    • Mysql
      • MySQL常见的索引引擎:MyISAM与InnoDB
      • 索引:数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。Mysql索引有:BTree索引和哈希索引。单条记录查询时哈希索引查询性能快,因为他底层数据结构就是一个哈希表;而BTree索引常用于其它类型的查询。
      • 缓存:数据库如果开启缓存,那么之后在同样的查询情况和数据下会直接在缓存中返回结果。然而缓存建立之后,Mysql会跟踪查询缓存涉及的每一个表,如果有某个表结构发生变化了,那么与这个表相关的所有的缓存数据都会失效。所以,缓存可以让数据库查询更便捷,但也会对数据库有一定影响,一般都把缓存空间设置为几十M,另外也会用sql_catch和sql_no_catch去管理Sql语句是否要进行缓存。
      • 数据库优化方案:1、表结构设计时优化:能使用数字类型时尽量使用数字类型,不要使用字符串类型。对于char和varchar要合理使用(char查询快,但占用空间多,一般对于长度变化不大的字段类型,范围为0——255;varchar查询慢,但节省空间,常用于变化大的数据,范围为0——65525)。字段长度在满足条件的情况下,不需设的太长,以提高查询速率,在建立索引时也可以减少资源的浪费。2、查询优化:能用简单查询实现的时候尽量不要使用表连接,在where后面尽量不要判断null,可以提前设置为默认为0。3、使用缓存。

      • MyISAM采用表级锁(table-level locking)。
        InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁。
        表级锁: Mysql中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单,资源消耗也比较少,加锁快,不会出现死锁。其锁定粒度最大,触发锁冲突的概率最高,并发度最低,MyISAM和 InnoDB引擎都支持表级锁。
        行级锁: Mysql中锁定 粒度最小 的一种锁,只针对当前操作的行进行加锁。 行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。
      • 视图,触发器,事物,存储过程:
        1 、视图:通过定义一个虚拟的表,保存下来,下次直接使用,可以不需要重复查询。
        create view 视图 as select * from xxxxx
        在硬盘里,视图只存在表结构文件,没有表数据文件。
        视图虽说用来查询,但是可以通过修改视图 里的数据来影响原始表的数据。因此尽量不要修改视图里的数据,同时,想去修改数据,还涉及到了跨部门沟通的问题,一般通过修改sql语句去替代。
        2、触发器:在满足所设定的条件下,会在我们对数据库的增删改 的时候自动触发相应的sql语句!
        create trigger 触发器名字 after insert on 表名 for each row
        begin
        sql语句
        end 在增加数据之后触发
        create trigger 触发器名字 before update on t1 for each row
        begin
        sql语句
        end 在修改数据之前
        3、事务:保证了我们操作的数据的安全。
        四个特性:
        原子性,一致性,隔离性,持久性
        简称acid
        使用:
        start transaction; 开启事务
        try:
        update user set bala = 90 where name = ‘asda’;
        update user set bala =80 where name = ‘dasd’;
        except:
        rollback; 回滚
        else:
        commit 只有提交后,数据才能真正写入硬盘
        4、存储过程:
        一组可编程的函数,为了完成特定功能的sql语句集,经过编译创建后保存在数据库中,用户可以通过使用指定的存储过程的名字并给定参数时区调用执行。
        为什么要用:
        1)将重复性很高的一些操作,封装到存储过程里,简化了对sql语句的操作
        2)统一了接口,确保数据的安全
        不过相对于oracle数据库而言,其的存储过程较弱,使用较少
    • Mysq与Oracle有哪些不同之处
      • Mysql比Oracle小
      • Oracle不开源,Mysql开源
      • Mysql和OracleSql写法有点不同:首先Mysql主键可以自动增长类型,Oracle不是;2、Oracle不能用双引号,Mysql可以;3、分页的话Mysql有limit就可以进行分页(“select… from …where…limit x, y”),而Oracle则需用到ROWNUM和嵌套查询。
      • 对事物支持:Mysql在InnoDB行级锁的情况下才支持事务,Oracle则是完全支持事务。
    展开全文
  • ACM算法总结 生成函数

    2020-07-29 11:50:16
    也叫母函数,常用来解决组合...一般来说普通的母函数为这样的形式 a0+a1x+a2x2+...+anxna_0+a_1x+a_2x^2+...+a_nx^na0​+a1​x+a2​x2+...+an​xn ,系数表示方案数,指数表示方案的状态。对于上面那个问题,可以转化..


    也叫母函数,常用来解决组合方面的问题。

    一个常见的例子如下:

    有 n 种硬币,每一种硬币的面值为 aia_i ,数目为 cic_i ,问用这些硬币可以组合出哪些数值的面值,并且各自有多少种组合方法。

    这显然是一个背包问题,但是我们考虑用生成函数来解决。一般来说普通的母函数为这样的形式 a0+a1x+a2x2+...+anxna_0+a_1x+a_2x^2+...+a_nx^n ,系数表示方案数,指数表示方案的状态。对于上面那个问题,可以转化为这样一个多项式乘法:
    i=1nj=0cixjai=(1+xa1+x2a1++xc1a1)(1+xa2++xc2a2)(1+xan++xcnan) \begin{aligned} &\prod\limits_{i=1}^{n}\sum\limits_{j=0}^{c_i}x^{ja_i} \\ =& (1+x^{a_1}+x^{2a_1}+\cdots+x^{c_1a_1})(1+x^{a_2}+\cdots+x^{c_2a_2})\cdots(1+x^{a_n}+\cdots+x^{c_na_n}) \end{aligned}
    把它展开之后,每个 x 的指数就表示了组成的面值,系数就表示了方案数。


    • 一道例题 Ignatius and the Princess III :给出正整数 N(1n1201\le n \le 120),问有多少种本质不同的方案可以使得 a1+a2+am=Na_1+a_2+\cdots a_m=N,并且满足 mN,ai>0m\le N,a_i>0 。这里本质不同指的是 1 2 11 1 2 算同一种方案。

    完全背包肯定是可以做的,生成函数的话可以考虑计算一个这样的式子:(1+x+x2+)(1+x2+x4+)(1+xN)(1+x+x^2+\cdots)(1+x^2+x^4+\cdots)\cdots(1+x^N) ,然后就可以了。

    代码:

    #define DIN freopen("input.txt","r",stdin);
    #define DOUT freopen("output.txt","w",stdout);
    #include <bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
    #define REP_(i,a,b) for(int i=(a);i>=(b);i--)
    #define pb push_back
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> P;
    int read()
    {
        int x=0,flag=1; char c=getchar();
        while((c>'9' || c<'0') && c!='-') c=getchar();
        if(c=='-') flag=0,c=getchar();
        while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return flag?x:-x;
    }
    
    const int maxn=120;
    int f[maxn+5],n,g[maxn+5];
    
    int main()
    {
        REP(i,0,maxn) f[i]=1;
        REP(k,2,maxn)
        {
            REP(i,0,maxn) for(int j=0;j+i<=maxn;j+=k)
                g[j+i]+=f[i];
            REP(i,0,maxn) f[i]=g[i],g[i]=0;
        }
        while(~scanf("%d",&n))
            printf("%d\n",f[n]);
    
        return 0;
    }
    


    • 再比如说一道稍微复杂一些的题目 Easy ,题意如下:给定三个正整数 N,M 和 K(1KN,M1061\le K\le N,M \le 10^6),如果找到两个正整数序列 A 和 B,满足 i=1KAi=N\sum\limits_{i=1}^KA_i=N 以及 i=1KBi=M\sum\limits_{i=1}^KB_i=M ,那么就可以获得收益 i=1Kmin(Ai,Bi)\prod\limits_{i=1}^K min(A_i,B_i) ,问可以获得的总收益是多少?

    先不考虑 min(Ai,Bi)min(A_i,B_i) 的收益,只考虑前面的条件限制,我们很容易列出生成函数 (x+x2+)K(y+y2+)K=(xy(1x)(1y))K(x+x^2+\cdots)^K(y+y^2+\cdots)^K=(\frac{xy}{(1-x)(1-y)})^K ,然后其中 xNyMx^Ny^M 的系数就是方案数,现在我们需要考虑的是对于每个 xiyjx^iy^j,给它赋予一个系数 min(i,j)min(i,j) 。因为每个 xiyjx^iy^j 实际上只是一个方案,如果我们可以把它变成 min(i,j)min(i,j) 个方案那就行了。所以把原生成函数转换为 (x+x2+)K(y+y2+)K(1+xy+(xy)2+)K=(xy(1x)(1y)(1xy))K(x+x^2+\cdots)^K(y+y^2+\cdots)^K(1+xy+(xy)^2+\cdots)^K=(\frac{xy}{(1-x)(1-y)(1-xy)})^K ,这样每个 xiyjx^iy^j 实际上也可以由 xi1yj1,,x1yji+1x^{i-1}y^{j-1},\cdots,x^{1}y^{j-i+1} 搭配 xyxy 的某个幂组合出来,所以原来的一个方案就变成了要求的系数。

    (xy(1x)(1y)(1xy))K(\frac{xy}{(1-x)(1-y)(1-xy)})^K 这个生成函数下,我们只需要计算出 xNyMx^Ny^M 的系数,这就是我们需要的答案。分子已经有了 xKyKx^Ky^K ,所以我们需要计算出 (1(1x)(1y)(1xy))K(\frac{1}{(1-x)(1-y)(1-xy)})^KxNKyMKx^{N-K}y^{M-K} 的系数,不难看出该式子是三个级数的乘积,对于 1(1x)n\frac{1}{(1-x)^n} 中某一项的系数的求法,有如下公式:

    根据广义二项式定理,有如下公式:

    (1+x)n=k=0(1)kCn+k1kxk(1+x)^{-n}=\sum\limits_{k=0}^{\infty}(-1)^kC_{n+k-1}^kx^k

    (1x)n=k=0Cn+k1kxk(1-x)^{-n}=\sum\limits_{k=0}^{\infty}C_{n+k-1}^kx^k

    所以,原问题的答案就是 ans=i=0NKCK+i1iCK+NKi1NKiCK+MKi1MKians=\sum\limits_{i=0}^{N-K}C_{K+i-1}^i C_{K+N-K-i-1}^{N-K-i}C_{K+M-K-i-1}^{M-K-i}

    代码:

    #define DIN freopen("input.txt","r",stdin);
    #define DOUT freopen("output.txt","w",stdout);
    #include <bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define REP(i,a,b) for(int i=(a);i<=(int)(b);i++)
    #define REP_(i,a,b) for(int i=(a);i>=(b);i--)
    #define pb push_back
    using namespace std;
    typedef long long LL;
    typedef vector<int> VI;
    typedef pair<int,int> P;
    int read()
    {
        int x=0,flag=1; char c=getchar();
        while((c>'9' || c<'0') && c!='-') c=getchar();
        if(c=='-') flag=0,c=getchar();
        while(c<='9' && c>='0') {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return flag?x:-x;
    }
    
    const int maxn=1e6+5,N=1e6;
    const LL M=998244353;
    LL inv[maxn],jie[maxn];
    
    LL ksm(LL x,LL n)
    {
        LL ret=1;
        while(n)
        {
            if(n&1) ret=ret*x%M;
            x=x*x%M;
            n>>=1;
        }
        return ret;
    }
    
    LL C(LL n,LL m)
    {
        if(n<0 || m<0 || n<m) return 0;
        if(!n || !m) return 1;
        return jie[n]*inv[m]%M*inv[n-m]%M;
    }
    
    int main()
    {
        jie[0]=1;
        REP(i,1,N) jie[i]=jie[i-1]*i%M;
    	REP(i,0,N) inv[i]=ksm(jie[i],M-2);
    	int T=read();
    	while(T--)
        {
            int n=read(),m=read(),k=read();
            if(n>m) swap(n,m);
            LL ans=0;
            REP(i,0,n-k)
            {
                LL x1=C(k+i-1,i);
                LL x2=C(k+n-k-i-1,n-k-i);
                LL x3=C(k+m-k-i-1,m-k-i);
                ans+=x1*x2%M*x3%M;
            }
            printf("%lld\n",ans%M);
        }
    
        return 0;
    }
    
    展开全文
  • <div><h1>Web性能领域常见的专业术语 测量与排查网页的性能瓶颈,是一名专业Web性能优化者的基本功。本章将详细介绍Web性能领域的一些专业术语,通过这些术语也可以侧面了解是哪些因素在影响加载性能。 ...
  • js常见面试题

    2021-02-27 09:11:03
    目录js事件循环机制(event loop)微任务与宏任务常见的状态码普通函数可以new吗addEventListener中第三个参数是干嘛的js垃圾回收机制什么是闭包以及应用场景js函数作用域链call、apply和bind的区别this指向原型与原型...

    js事件循环机制(event loop)

    同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
    当指定的事情完成时,Event Table会将这个函数移入Event Queue。
    主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
    上述过程会不断重复,也就是常说的Event Loop(事件循环)。

    例如:

    console.log(1);
    setTimeout(()=>{
    	console.log(3);
    },100)
    console.log(2);
    

    js自上而下执行,先执行console.log(1);输出1,然后执行定时器setTimeout,由于setTimeout是异步的,所以先将setTimeout存放在Event Table,再然后执行console.log(2);输出2,当代码执行完成后会去检测Event Queue,如果有则执行,没有即等待,当100ms过去后setTimeout将进入Event Queue,再然后主线程没有任务执行时将setTimeout取出推入主线程开始执行setTimeout

    在这里插入图片描述

    微任务与宏任务

    宏任务(macrotask )和微任务(microtask ) 表示异步任务的两种分类。常见宏任务:I/O 、setTimeout、setInterval;微任务:Promise.then catch finally、process.nextTick

    例如

    setTimeout(()=>{
    	console.log(4)
    })
    new Promise((res,rej)=>{
    	console.log(1)
    	res()
    })
    .then(()=>{
    	console.log(3)
    })
    console.log(2)
    

    代码执行先遇到setTimeout,推入Event Table,然后遇到Promise,执行Promise内部代码输出1,再执行res,遇到Promise.then推入Event Table,然后执行输出2,再然后由于Promise.then是微任务,setTimeout是宏任务,所以先将Promise.then推入Event Queue,再推setTimeout,则主线程先执行Promise.then再执行setTimeout;
    每次宏任务执行完后都会清空队列里的微任务,微任务执行优先级高于宏任务。

    常见的状态码

    200,
    201表示请求成功且服务器创建了新的资源
    202表示服务器已经接受了请求,但还未处理
    301,302重定向
    304表示自从上一次请求以来,页面的内容没有改变过
    404,
    500服务器错误
    503表示服务器暂时无法处理请求

    普通函数可以new吗

    可以,但是没有什么意义。(返回一个空的this有何用?)
    例如

    function a(){
    
    }
    console.log(new a());//a{}
    

    addEventListener中第三个参数是干嘛的

    控制函数是在捕获阶段执行还是再冒泡阶段执行,默认冒泡阶段false

    js垃圾回收机制

    当一个变量的生命周期结束之后它所指向的内存就应该被释放。JS有两种变量,全局变量和在函数中产生的局部变量。局部变量的生命周期在函数执行过后就结束了,此时便可将它引用的内存释放(即垃圾回收),但全局变量生命周期会持续到浏览器关闭页面。
    回收有两种方式:标记清除、引用计数。
        标记清除:大部分浏览器以此方式进行垃圾回收,当变量进入执行环境(函数中声明变量)的时候,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”,在离开环境之后还有的变量则是需要被删除的变量。
        引用计数:机制就是跟踪一个值的引用次数,当声明一个变量并将一个引用类型赋值给该变量时该值引用次数加1,当这个变量指向其他一个时该值的引用次数便减一。当该值引用次数为0时就会被回收。

    什么是闭包以及应用场景

    函数嵌套函数,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。例如:

    function addOne(){
        var a = 10; 
        function fn(){
            a++;
            console.log(a);
        }
        return fn; 
    }
    

    应用场景
        读取函数内部的变量
        变量的值始终保持在内存中
        模拟块级作用域(匿名自执行函数)

    for(var i=0;i<5;i++){
        (function(i){ 
            setTimeout(()=>{
            	console.log(i);
        	}) 
        })(i);
    }
    

        回调函数读取外部变量
        可以给无法处理函数参数的函数,处理参数
    解决闭包造成的内存泄漏
        通过添加另一个函数来避免闭包本身,进而阻止内存泄漏
        主动设置为空,打破循环引用

    js函数作用域链

    js函数作用域链是从定义处开始逐层向外查找,而非被调用处

    call、apply和bind的区别

    ind不会立即执行,需手动调用; apply, call则是立即调用。
    例如

    var obj = {
    	name : 'wang'
    }
    function start(){
    	console.log(this.name);
    }
    start.bind(obj)()
    start.call(obj)
    start.apply(obj)
    

    apply, call的区别

    Object.call(this,obj1,obj2,obj3)
    Object.apply(this,arguments)
    

    手动实现call、apply和bind

    function start(sex,age){
    	this.sex = sex;
    	this.age = age;
    	return this;
    }
    obj = {
    	name : '风舞红枫'
    }
    

    mybind

    Function.prototype.mybind = function(context) {
    	if (typeof this !== 'function') {
    		return new Error("不是一个函数");
    	}
    	console.log(context,arguments)
    	var arg = [...arguments].slice(1);
    	return function(){
    		return start.apply(context,arg);
    	}
    }
    var result = start.mybind(obj,'男','16')();
    console.log(result);
    

    mycall

    Function.prototype.mycall = function(context) {
    	if (typeof this !== 'function') {
    		return new Error("不是一个函数");
    	}
    	console.log(context,this)
    	var arg = [...arguments].slice(1);
    	context.fn = this;
    	var result = context.fn(...arg);
    	delete context.fn;
    	return result;
    }
    var result = start.mycall(obj,'男','16');
    console.log(result);
    

    myapply

    Function.prototype.myapply = function(context) {
    	if (typeof this !== 'function') {
    		return new Error("不是一个函数");
    	}
    	var arg = arguments[1];
    	context.fn = this;
    	if (arg) {
    		result = context.fn(...arguments[1]);
    	} else {
    		result = context.fn();
    	}
    	delete context.fn;
    	return result;
    }
    var result = start.myapply(obj,['男','16']);
    console.log(result);
    

    this指向

    先即以下两条,再往下看
        1、this指向直接调用者;
        2、找不到调用者时即为window;
    例1:

    function fun(){
       console.log(this.num);
    }
    var obj = {
        num:'1',
        f:fun
    }
    var num = 2;
    obj.f(); //1 此处是obj调用了函数fun,所以fun函数内this指向obj,故而输出1
    fun(); //2	此处无明显调用者,顾指向window,所以输出2
    

    例2(同理):

    var A = {
       name: '张三',
       f: function () {
           console.log(this.name);
       }
    };
    var B = {
       name: '李四'
    };
    B.f = A.f;
    B.f()   //李四
    A.f()   //张三
    

    例3:

    function foo() {
        console.log(this.a);
    }
    var obj2 = {
        a: 2,
        fn: foo
    };
    var obj1 = {
        a: 1,
        o1: obj2
    };
    obj1.o1.fn(); //2 此处fn的直接调用者是o1,即obj2;
    

    例4:

    function C(){
      this.a = 37;
    }
    var o = new C();
    console.log(o.a); //37 构造函数无return时默认返回this
    function C2(){
      this.a = 37;
      return {a:38};
    }
    o = new C2();
    console.log(o.a); //38 手动设置了返回对象
    

    例5:

    var a = 1;
    setTimeout(function(){
    	console.log(this.a)	//1 定时器中的this指向window
    },100)
    

    例6:

    var a = 1;
    function(){
    	console.log(this.a)	//1 匿名函数的this指向window
    }()
    让匿名函数中的this指向对象的两种方法
    	可以使用对象冒充强制改变this的指向
    	将this赋值给一个变量,闭包访问这个变量
    

    call、applay、bind不做例子
    箭头函数的this指向为其父级/宿主

    原型与原型链

    原型
        1、原型就是一个属性,这个属性是构造函数的属性,构造函数是用来制造用来出对象的,是构造函数制造出来的公共祖先,后面所有的对象都会继承原型的属性与方法(原型也是个对象)
        2、__proto__这个是用来查看原型的,这个是对象的属性,这个属性可以查看但是不能修改(隐式属性)
        3、prototype 设置原型,这个是构造函数的属性
    原型链
        由于__proto__是任何对象都有的属性,而js里万物皆对象,所以会形成一条__proto__连起来的链条 ,递归访问__proto__必须最终到头,并且值是null。
    例如

    Object.prototype.toString=function(){
    console.log('找到我没有呀?');
    }
    var func = function(){};
    var obj = new func();
    
    console.log(obj.__proto__ === func.prototype) //true
    console.log(func.prototype.__proto__ === Object.prototype) //true
    // console.log(func.__proto__ === Function.prototype) //true
    // console.log(Function.prototype.__proto__ === Object.prototype) //true
    console.log(Object.prototype.__proto__ === null)
    
    obj.toString();//此时先在obj中找toString,没有找到后沿着obj.__proto__到了func.prototype。发现func.prototype也没有,再然后沿着func.prototype.__proto__到了Object.prototype,最后找到了toString
    
    console.log(obj.constructor === func) //true
    console.log(func.constructor.prototype.__proto__ === Object.prototype) //true
    console.log(func.constructor === Function) //true
    console.log(func.constructor.__proto__ === Function.prototype) //true
    console.log(Function.constructor.prototype.__proto__ === Object.prototype) //true
    console.log(Object.constructor.prototype.__proto__ === Object.prototype) //true
    

    继承

    原型链继承
    即在prototype上new一个你要继承的那个对象(如:Run.prototype=new Show();会覆盖掉原本的prototype)

    function Person(){
    	this.name="wang";
    }
    function Boy(){
    	this.age="20"; 
    }
    Boy.prototype=new Person();//Boy继承了Person,通过原型,形成链条
    var boy=new Boy();
    console.log(boy.name)//wang
    

    构造函数继承(对象冒充继承)
    为了解决引用共享和超类型无法传参的问题,我们采用一种叫借用构造函数的技术,或者成为对象冒充(伪造对象、经典继承)的技术来解决这两种问题

    function Person(age){
    	this.age=age;
    }
    function Boy(age){
    	Person.call(this,age); //对象冒充,给超类型传参
    }
    var boy = new Boy(22);
    console.log(boy.age);//22
    

    组合继承(原型链继承+构造函数继承)
    借用构造函数虽然解决了刚才两种问题, 但没有原型, 复用则无从谈起。 所以,我们需要原型链+借用构造函数的模式,这种模式成为组合继承。

    function Person(age) {
    	this.age = age;
    }
    Person.prototype.say = function () {
    	return '我今年' + this.age + '岁';
    };
    function Boy(age) {
    	Person.call(this, age); //对象冒充
    }
    Boy.prototype = new Person(); //原型链继承
    var boy = new Boy(100);
    console.log(boy.say());
    

    原型式继承

    function obj(data) { //传递一个字面量函数
    	function F() {} //创建一个构造函数
    	F.prototype = data; //把字面量函数赋值给构造函数的原型
    	return new F(); //最终返回出实例化的构造函数
    }
    var data = { //字面量对象
    	type : '年龄',
    	arr : [21,22,23]
    };
    var data1 = obj(data); //传递
    console.log(data1.type); //'年龄'
    console.log(data1.arr); //[21,22,23]
    
    data1.type = '年龄呀';
    data1.arr.push(24);
    console.log(data1.type); //'年龄呀'
    console.log(data1.arr); //[21,22,23,24]
    
    var data2 = obj(data); //传递
    console.log(data2.type); //'年龄'
    console.log(data2.arr); //[21,22,23,24] 引用类型共享了
    

    get与post的区别

    其实没有本质的区别,只是习惯get的请求参数放到url中,post的请求参数放到body中。
    get请求将参数放在body中也不会报错,post同理,一切只源于潮流…

    常用的方法

    字符串常用方法
        toLowerCase(): 把字符串转为小写,返回新的字符串。
        toUpperCase(): 把字符串转为大写,返回新的字符串。
        indexOf(): 返回某个指定的子字符串在字符串中第一次出现的位置
        lastIndexOf(): 返回某个指定的子字符串在字符串中最后出现的位置。
        slice(): 返回字符串中提取的子字符串。
        substring(): 提取字符串中介于两个指定下标之间的字符。
        substr(): 返回从指定下标开始指定长度的的子字符串。
        split(): 把字符串分割成字符串数组。
        replace(): 在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串。
    数组常用方法
        push(n): 从数组的尾部添加一个元素n,返回这个添加的元素n
        pop(): 从数组的尾部删除一个元素,返回这个删除的元素,不接收参数
        unshift(n): 从数组的头部添加一个元素n,返回这个添加的元素n,原数组发生改变
        shift(): 从数组的头部删除一个元素,返回这个删除的元素,不接收参数
        slice(): 返回数组中提取的子数组。
        splice(i,n,m,m,m,…): 从数组下标i开始,删除项目n个,然后添加项目m。
        reverse(): 数组翻转,该方法会改变原来的数组,而不会创建新的数组
        sort(): 无参数默认从小到大排序,判断方式:按位判断
        concat(): 数组拼接
        join(’-’): 将数组转化为为字符串,以括号内的拼接

    两=与三=的不同

    两=直接判断值是否相等
    三=会判断类型是否相同

    判断类型的方法有哪些

    typeof
    	typeof "";  //string
    	typeof 1;   //number
    	typeof false; //boolean
    	typeof undefined; //undefined
    	typeof function(){}; //function
    	typeof []; //object
    	typeof {}; //object
    	typeof Symbol(); //symbol
    	typeof null; //object
    	typeof new Date(); //object
    	typeof new RegExp(); //object
    instanceof
    	{} instanceof Object; //true
    	[] instanceof Array;  //true
    	[] instanceof Object; //true
    	"123" instanceof String; //false
    	new String(123) instanceof String; //true
    constructor
    	"".constructor //ƒ String() { [native code] }
    	"".constructor == String //true
    	1.constructor //报错 Invalid or unexpected token
    	new Number(1).constructor //ƒ Function() { [native code] }
    	new Number(1).constructor == Number //false
    	new Date().constructor //ƒ Date() { [native code] }
    	new RegExp().constructor //ƒ RegExp() { [native code] }
    Object.prototype.toString()
    	Object.prototype.toString.call(""); //[object String]
    	Object.prototype.toString.call(1); //[object Number]
    	Object.prototype.toString.call(false); //[object Boolean]
    	Object.prototype.toString.call(undefined); //[object Undefined]
    	Object.prototype.toString.call(function(){}); //[object Function]
    	Object.prototype.toString.call([]); //[object Array]
    	Object.prototype.toString.call({}); //[object Object]
    	Object.prototype.toString.call(Symbol()); //[object Symbol]
    	Object.prototype.toString.call(null); //[object Null]
    	Object.prototype.toString.call(new Date()); //[object Date]
    	Object.prototype.toString.call(new RegExp()); //[object RegExp]
    

    封装返回数据类型的方法:

    function dataType(obj){
    	return Object.prototype.toString.call(obj).replace(/(\[object )|\]/g,"")
    }
    

    null和undefined的区别

    null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。当声明的变量还未被初始化时,变量的默认值为undefined。 null用来表示尚未存在的对象
    undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
        (1)变量被声明了,但没有赋值时,就等于undefined。
        (2)调用函数时,应该提供的参数没有提供,该参数等于undefined。
        (3)对象没有赋值的属性,该属性的值为undefined。
        (4)函数没有返回值时,默认返回undefined。
    null表示"没有对象",即该处不应该有值。典型用法是:
        1) 作为函数的参数,表示该函数的参数不是对象。
        (2) 作为对象原型链的终点。

    new操作符具体干了什么

    1、创建一个空的对象 var obj=new Object();
    2、让空对象的原型属性指向原型链,设置原型链 obj.proto=Func.prototype;
    3、让构造函数的this指向obj,并执行函数体 var result=Func.call(obj);
    4、判断返回类型,如果是值就返回这个obj,如果是引用类型,返回这个引用对象。

    ajax原理

    1、创建对象
    var xhr = new XMLHttpRequest();
    2、打开请求
    xhr.open(‘GET’, ‘example.txt’, true);
    3、发送请求
    xhr.send(); 发送请求到服务器
    4、接收响应
    xhr.onreadystatechange =function(){}
    (1)当readystate值从一个值变为另一个值时,都会触发readystatechange事件。
    (2)当readystate==4时,表示已经接收到全部响应数据。
    (3)当status ==200时,表示服务器成功返回页面和数据。
    (4)如果(2)和(3)内容同时满足,则可以通过xhr.responseText,获得服务器返回的内容。

    从输入URL到页面加载发生了什么

    1、DNS解析
        将域名转化为IP地址的工作。
        如果浏览器有缓存,直接使用浏览器缓存,否则使用本级缓存,再没有就使用host;如果本地没有,就向dns域名服务器查询到对应的IP
        由于dns的解析很耗时,当解析域名过多的时候,便会导致首屏加载变得过慢。
    2、TCP连接
        建立连接的三次握手
            客户端:hello,你是服务端么?
            服务端:hello,我是服务端,你是客户端么?
            客户端:yes,我是客户端。
    3、发送HTTP请求
    4、服务器处理请求并返回HTTP报文
    5、浏览器解析渲染页面
        (1)处理HTML标记,构建DOM树;
        (2)处理CSS标记,构建CSSOM树;
            默认情况下,CSS是阻塞加载的,但它并不会阻塞DOM树的解析,它阻塞的是DOM的渲染,直至CSSOM树构建完成。因而为了避免看到长时间的白屏,我们尽可能早地提前加载CSS文件
        (3)将DOM树和CSSOM树合并成渲染树;
        (4)布局渲染树,计算各元素的尺寸、位置;
        (5)绘制渲染树,绘制页面像素信息。
    6、连接结束
        断开连接的四次挥手
            主动方:我已经关闭了向你那边的主动通道了
            被动方:收到通道关闭的信息
            被动方:那我也告诉你,我这边向你的主动通道也关闭了
            主动方:最后收到数据,之后双方无法通信

    offsetX, clientX, pageX, screenX, layerX, x

    offsetX:点击位置距离当前元素左边的距离(padding处算起始点)
    clientX:点击位置距离浏览器窗口左边的距离
    pageX:点击位置距离文档左边的距离
    screenX:点击位置距离屏幕左边的距离
    layerX:在点击元素设置相对定位或绝对定位时layerX == offsetX,(layerX是从border处算起始点)
    x:xclientX(其他),xlayerX(IE)

    防抖和节流

    1.防抖(debounce):触发高频事件 n 秒后函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间
        举例:就好像在百度搜索时,每次输入之后都有联想词弹出,这个控制联想词的方法就不可能是输入框内容一改变就触发的,他一定是当你结束输入一段时间之后才会触发。
    2.节流(thorttle):高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率
        举例:预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。就好像你在淘宝抢购某一件限量热卖商品时,你不断点刷新点购买,可是总有一段时间你点上是没有效果,这里就用到了节流,就是怕点的太快导致系统出现bug。

    区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。

    常见的浏览器兼容

    1.事件对象创建的兼容:
        var e=e || event
    2.鼠标事件对象的属性
        Button属性 左键为0 右键为2 滚轮为1;
        IE 左键为1 右键为2 滚轮为4;
    3.键盘事件对对象的属性
        Keycode 获取键盘的按键值 值为AscII码值
        兼容:e.keycode||e.which;
    4.阻止事件冒泡兼容
        e.stopPropagation?e.stopPropagation:cancleBubble=true;
    5. 事件监听
        绑定事件监听
            addEventListener(); ie:attachEvent()
        取消事件监听
            removeEventListener(); ie:detachEvent()
    6. 阻止浏览器的默认行为:
        兼容写法 e.preventDefault?e.preventDefault():e.returnValue=false;
        万能:return false(写在最后面);
    7. 事件的委托
        var e.target(其他)||e.srcElement(IE);
    8. 获取页面滚走的距离
        document.documentElement.scrollTop||document.body.ScrollTop;
    9. 拖拽里面获取鼠标距离按下元素的内部偏移量:
        var disx= e.offsetX||e.layerX;
    10.获取某元素的非行内样式:
        window.getComputedStyle?window.getComputedStyle(对象,false)[“属性”]:对象.currentStyle[“属性”]
    11.获取可见区域宽高
        在IE中:
            document.body.clientWidth ==> BODY对象宽度
            document.body.clientHeight ==> BODY对象高度
            document.documentElement.clientWidth ==> 可见区域宽度
            document.documentElement.clientHeight ==> 可见区域高度
            document.documentElement.scrollTop =>窗口滚动条滚动高度
        在FireFox中:
            document.body.clientWidth ==> BODY对象宽度
            document.body.clientHeight ==> BODY对象高度
            document.documentElement.clientWidth ==> 可见区域宽度
            document.documentElement.clientHeight ==> 可见区域高度
            document.documentElement.scrollTop =>窗口滚动条滚动高度
        在chrome中:
            document.body.clientWidth ==> BODY对象宽度
            document.body.clientHeight ==> BODY对象高度
            document.documentElement.clientWidth ==> 可见区域宽度
            document.documentElement.clientHeight ==> 可见区域高度
            document.body.scrollTop =>窗口滚动条滚动高度
        在Opera中:
            document.body.clientWidth ==> 可见区域宽度
            document.body.clientHeight ==> 可见区域高度
            document.documentElement.clientWidth ==> 页面对象宽度(即BODY对象宽度加上Margin宽)
            document.documentElement.clientHeight ==> 页面对象高度(即BODY对象高度加上Margin高
        滚动到顶部 window.scrollTo(0,0)
        滚动到尾部 window.scrollTo(0,document.body.clientHeight)

    代码练习题

    1.变量提升面试题

    var a = 100;  
    function test(){  
    	console.log(a);  
    	a = 10;  //去掉了var就变成定义了全局变量了
    	console.log(a);  
    }  
    test();
    console.log(a);
    依次输出 100 10 10
    

    2.变量提升面试题

    var a = 100;  
    function test(){  
    	console.log(a);  
    	var a = 10;
    	console.log(a);  
    }  
    test();
    console.log(a);
    

    3.this指向面试题

    var x = 3;
    var y = 4;
    var obj = {
        x: 1,
        y: 6,
        getX: function() {
            var x =5;
            return function() {
                return this.x;
            }();
        },
        getY: function() {
            var y =7;
            return this.y;
        }
    }
    console.log(obj.getX())//3
    console.log(obj.getY())//6
    

    4.this指向面试题

    var obj = {
        a: 1,
        b: function(){
            return function(){
                console.log(this) //window
            }
        }
    }
    var objf = obj.b();
    objf();
    var obj2 = {
        a: 1,
        b: function(){
            return ()=>{
                console.log(this) //obj2
            }
        }
    }
    var objf2 = obj2.b();
    objf2();
    
    展开全文
  • Vue 常见技术面试题

    2021-01-08 11:55:41
    Vue拦截器vuex状态管理vue生命周期、常见的生命周期函数用过哪些vue ui框架vue中的router和route的区别计算属性和侦听属性的区别vue里面delete跟vue.delete什么区别?如果一个空白页面使用弹窗this,那么this会弹...
  • 78.常见的异常类有哪些? 八、网络 79.http 响应码 301 和 302 代表的是什么?有什么区别? 80.forward 和 redirect 的区别? 81.简述 tcp 和 udp的区别? 82.tcp 为什么要三次握手,两次不行吗?为什么? 83.说一下...
  • 不同编译器给出不同结果, 有的为 3, 有的为 4, 哪个是正确? o 4.4 这是个巧妙表达式: a ^= b ^= a ^= b 它不需要临时变量就可以交换 a 和 b 值。 o 4.5 我可否用括号来强制执行我所需要计算顺序? o ...
  • Stateful Session Bean 与 Stateless Session Bean ,这两种的 Session Bean都可以将系统逻辑放在 method之中执行,不同的是 Stateful Session Bean 可以记录呼叫者的状态,因此通常来说,一个使用者会一个相对应...
  • Java反射机制

    2020-08-11 14:36:41
    3 种方法8、创建对象两种方法二、其他内容1、反射机制优缺点2、反射机制应用场景有哪些?3、Java获取反射三种方法 一、反射机制概念 1、动态语言 动态语言,是指程序在运行时可以改变其结构:新的函数可以引进...
  • 原生JS面试题5

    2020-04-22 12:08:35
    十九、简述 ajax 的过程 1. 创建XMLHttpRequest对象,也就是创建一个异步调用对象 ...3. 设置响应HTTP请求状态变化的函数 ...5. 获取异步调用返回的数据 ...http 常见的状态有哪些?分别代表什么? 200 - 请求成功 3...
  • 22、面向对象特征有哪些方面 15 23、java中实现多态机制是什么? 17 24、abstract class和interface有什么区别? 17 25、abstractmethod是否可同时是static,是否可同时是native,是否可同时是synchronized? 18 ...
  • 读者将要学习如何使用类方法来确定输入或输出流的状态, 了解输入类型是否不匹配或是否检测到了文件尾。C++使用继承来派生用于管理文件输入和输出的类。 读者将学习如何打开文件,以进行输入和输出,如何在文件中...
  • 读者将要学习如何使用类方法来确定输入或输出流的状态, 了解输入类型是否不匹配或是否检测到了文件尾。C++使用继承来派生用于管理文件输入和输出的类。 读者将学习如何打开文件,以进行输入和输出,如何在文件中...
  • 读者将要学习如何使用类方法来确定输入或输出流的状态, 了解输入类型是否不匹配或是否检测到了文件尾。C++使用继承来派生用于管理文件输入和输出的类。 读者将学习如何打开文件,以进行输入和输出,如何在文件中...
  • 在MFC框架调用该函数的时候,重新定义它的状态和行为; 一般来说,应用程序可以通过以下两种途径来实现以上的方法: 1. 在父窗口里,截获自身的或者由子元素(包括控件和菜单等元素)传递的关于界面绘制的消息; 2....
  • 在zepto中一个常见的jsonp请求配置就是这样了,大家都很熟悉了。但是不知道大家没有发现. <ol><li>如果设置了<code>timeout超时了,并且没有设置<code>jsonpCallback字段,那么控制台几乎都会...
  • 答:ARM架构Linux内核中,5种常见的异常,其中中断异常是其一,Linux内核将所有中断统一编号,使用一个irq_desc结构体来描述这些中断,里面记录了中断名称、中断状态、中断标记、并提供了中断的底层硬件访问函数...
  • 1.1.8 NFS 和 SMB 是最常见的两种 NAS(Network Attached Storage)协议,当把一个文件系统同时通过 NFS 和 SMB 协议共享给多个主机访问时,以下哪些说法是错误的 1.1.9 输入 ping IP 后敲回车,发包前会发生什么?...
  • Singleton 通常被用来代表一个无状态对象,如函数,或者哪些本质上唯一的系统组件。 2. 实现 Singleton 两种常见的方法。这两种方法都要保持构造器为私有的,并导出公有的静态成员,以便允许客户端能够访问该类的...
  • 2.25.6 常见的函数有哪些? 69 2.25.6 软间隔与正则化 73 2.25.7 SVM主要特点及缺点? 73 2.26 贝叶斯 74 2.26.1 图解极大似然估计 74 2.26.2 朴素贝叶斯分类器和一般的贝叶斯分类器有什么区别? 76 2.26.4 朴素与...
  • C++程序员面试宝典

    热门讨论 2013-04-01 13:36:19
    有哪些特别类成员函数 135 面试题124 什么是静态函数?如何使用静态函数 136 面试题125 静态函数能访问类私有成员 137 面试题126 一个类可以访问另一个类私有成员吗 137 11.4 函数重载 138 面试题127 函数重载...
  • 实际上常见的解决方案是建立如下所示的循环: Randomize RNumber = Int(Rnd*499) +1   While Not objRec.EOF If objRec("ID") = RNumber THEN ... 这里是执行脚本 ... end if objRec.MoveNext Wend  这很...
  • 微信web开发者工具

    2018-04-26 14:31:10
    pages->设置页面路径,接受一个数据,每一项都是字符串,来指定小程序有哪些页面构成,每一项代表对应页面的【路径+文件名】信息,数据的第一项为小程序的首页。 windows->设置默认页面的窗口表现(用于设置小程序...
  • 39、说出十种常见的异常 22 40什么是检查性异常和非检查性异常? 23 41、Java的异常处理机制是什么? 23 42、一个静态方法,里面可不可以用this和super关键字 24 三、JavaScript/JQuery/Ajax部分 24 1、用js和jQuery...
  • 引起LNK2001的常见错误都有哪些 如何调试Windows外壳扩展程序(Shell Extension) 如何调试一个没有原码exe文件调用 dll 怎样设置栈大小 如何知道GetLastError()返回错误代码意义 如何使用Visual C++ 6.0...
  • java面试宝典

    2013-02-28 16:04:01
    1、面向对象特征有哪些方面? 8 2、作用域public,private,protected,以及不写时区别? 8 3、String 是最基本数据类型吗? 8 4、float 型float f=3.4是否正确? 8 5、语句float f=1.3;编译能否通过? 8 6、short ...
  • 千方百计笔试题大全

    2011-11-30 21:58:33
    1、面向对象特征有哪些方面? 8 2、作用域public,private,protected,以及不写时区别? 8 3、String 是最基本数据类型吗? 8 4、float 型float f=3.4是否正确? 8 5、语句float f=1.3;编译能否通过? 8 6、short ...
  • java 面试题 总结

    2009-09-16 08:45:34
    1、面向对象特征有哪些方面 1.抽象: 抽象就是忽略一个主题中与当前目标无关那些方面,以便更充分地注意与当前目标有关方面。抽象并不打算了解全部问题,而只是选择其中一部分,暂时不用部分细节。抽象包括...
  • 有哪些主要软件开发方法? 答:主要软件开发方法有:结构化开发方法、Jackson(JSP、JSD)方法、原型化开发方 法、维也纳开发方法(VDM)和面向对象开发方法。 6. 软件生命期各阶段任务是什么? 答:软件...

空空如也

空空如也

1 2 3 4
收藏数 65
精华内容 26
关键字:

常见的状态函数有哪些