JavaScript-笔记1

遍历数组:
            var tmpLines = []
            // $scope.todos.forEach(element => {
            // if(!element.isChecked)
            // {
            // tmpLines.push(element);
            // }
            // $scope.todos = tmpLines;
            // });
            $scope.todos.forEach(function(item, index){
                if(!item.isChecked){
                    tmpLines.push(item);
                }
            })
            $scope.todos = tmpLines;        
常用console.log(xxx)来打印变量,方便调试; 浏览器按F12可以用于调试和查看变量的值
常用alert()弹框.
 
那些老旧的实例可能会在 <script> 标签中使用 type="text/javascript"。现在已经不必这样做了。JavaScript 是所有现代浏览器以及 HTML5 中的默认脚本语言。
HTML 中的脚本必须位于 <script> 与 </script> 标签之间。
脚本可被放置在 HTML 页面的 <body> 和 <head> 部分中。
 
console.log()的用处:主要是方便你调式javascript用的, 你可以看到你在页面中输出的内容。
相比alert他的优点是:
他能看到结构化的东西,如果是alert,弹出一个对象就是[object object],但是console能看到对象的内容。
console不会打断你页面的操作,如果用alert弹出来内容,那么页面就死了,但是console输出内容后你页面还可以正常操作。
 
命名方式:
1.匈牙利命名方式:变量名+对象描述 整数i 浮点fl 布尔b 字符串s 数组a 对象o 函数fn 正则re 例:iAge = 18;
2.驼峰命名:
 (1)全部小写:单词与单词间全部用下划线分割
 (2)大小写混合:每个单词的第一个字母大写,例:gongZuoNianXian
在 JavaScript 中,用分号来结束语句是可选的,推荐除{}外均加上分号。(JavaScript 中,分号是可选的,在缺少了分号就无法正确解析代码的时候,JavaScript 才会填补分号)
 
JavaScript是弱类型编程语言,定义变量都使用 var 定义,与 Java 这种强类型语言有区别.
在定义后可以通过 typeOf() 来获取JavaScript中变量的数据类型.
// Number 通过数字字面量赋值 
 // Number 通过表达式字面量赋值
// String 通过字符串字面量赋值
// Array 通过数组字面量赋值 
// Object 通过对象字面量赋值
有个情况需要特别注意: typeof 不能用来判断是 Array 还是Object
var arr = [] typeof(arr) === 'object' // true
结果为 true。
当然你可以使用其他方式来判断:
1、使用 isArray 方法
var cars=new Array();
cars[0]="Saab";
cars[1]="Volvo";
cars[2]="BMW";
// 判断是否支持该方法
if (Array.isArray) {
    if(Array.isArray(cars)) {
        document.write("该对象是一个数组。") ;
    }
}
2、使用 instanceof 操作符
var cars=new Array();
cars[0]="Saab";
cars[1]="Volvo";
cars[2]="BMW";
if (cars instanceof Array) {
    document.write("该对象是一个数组。") ;
}
 
数组的创建和初始化方式:
var cars=new Array();
cars[0]="Saab";
cars[1]="Volvo";
cars[2]="BMW";
或者 (condensed array):
var cars=new Array("Saab","Volvo","BMW");
或者 (literal array):
var cars=["Saab","Volvo","BMW"];
注:js中数组也是object,允许元素不同类型,很像python中的list.
typeof 用以获取一个变量或者表达式的类型,typeof 一般只能返回如下几个结果:
number,boolean,string,function(函数),object(NULL,数组,对象),undefined。
我们可以使用 typeof 来获取一个变量是否存在,如 if(typeof a!="undefined"){},而不要去使用 if(a) 因为如果 a 不存在(未声明)则会出错。
正因为 typeof 遇到 null,数组,对象时都会返回 object 类型,所以当我们要判断一个对象是否是数组时。
或者判断某个变量是否是某个对象的实例则要选择使用另一个关键语法 instanceof。可通过 instanceof 操作符来判断对象的具体类型。eg:arr instanceof Array
 
undefined与null的区别:
null 表示一个值被定义了,定义为“空值”;null是一个只有一个值的特殊类型。表示一个空对象引用。也可以用来清空对象.
undefined 表示根本不存在定义。
所以设置一个值为 null 是合理的,如:objA.valueA = null;但设置一个值为 undefined 是不合理的
Number(null)等于0;Number(undefined)为NaN;null==undefined为true;null===undefined为false
在 JavaScript 中, undefined 是一个没有设置值的变量。
typeof 一个没有值的变量会返回 undefined。
任何变量都可以通过设置值为 undefined 来清空。 类型为 undefined.
1、定义
 (1)undefined:是所有没有赋值变量的默认值,自动赋值。
 (2)null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。
2、何时使用null?
当使用完一个比较大的对象时,需要对其进行释放内存时,设置为 null。(类似于空指针)
3、null 与 undefined 的异同点是什么呢?
共同点:都是原始类型,保存在栈中变量本地。
不同点:
(1)undefined——表示变量声明过但并未赋过值。
它是所有未赋值变量默认值,例如:
var a; // a 自动被赋值为 undefined
(2)null——表示一个变量将来可能指向一个对象。
一般用于主动释放指向对象的引用,例如:
var emps = ['ss','nn'];
emps = null; // 释放指向数组的引用
4、延伸——垃圾回收站
它是专门释放对象内存的一个程序。
 (1)在底层,后台伴随当前程序同时运行;引擎会定时自动调用垃圾回收期;
 (2)总有一个对象不再被任何变量引用时,才释放。
 
在 JavaScript 中, null 用于对象, undefined 用于变量,属性和方法。
对象只有被定义才有可能为 null,否则为 undefined。
如果我们想测试对象是否存在,在对象还没定义时将会抛出一个错误。
错误的使用方式:
if (myObj !== null && typeof myObj !== "undefined") 
正确的方式是我们需要先使用 typeof 来检测对象是否已定义:
if (typeof myObj !== "undefined" && myObj !== null) 
 
NaN原始值:
NaN 是一个特殊的数值,NaN 即非数值(Not a Number),这个数值用于本来要返回数值的操作数未返回数值的情况。
NaN 与任何值都不相等,包括 NaN 本身。
可以通过 isNaN() 方法来判断某个数值是否是NaN这个特殊的数,使用 isNaN() 方法会将传入的数值如果是非数值的会将其自动转换成数值类型,若能转换成数值类型,那么这个函数返回 false,若不能转换成数值类型,则这个数就是 NaN,即返回 true。
 
 
 
创建对象的两种方式:
第一种:有返回值,无需new
function Demo(){
    var obj=new Object();
    obj.name="张思";
    obj.age=12;
    obj.firstF=function(){
    }
    obj.secondF=function(){
    }
    return obj;
}
var one=Demo();
// 调用输出
document.write(one.age);
第二种:无返回值,因此需要利用new返回一个对象实例
function Demo(){
    this.name="张思";
    this.age=12;
    this.firstF=function(){
    }
    this.secondF=function(){
    }
}
var one=new Demo    //或new Demo()
// 调用输出
document.write(one.age);
第三种:直接定义对象实例,无需先定义类再创建
js允许先声明一个对象object变量,再往里面添加属性和方法.
var person = new Object;
    console.log(person);
    person.name = "bob";
    person.age = 12;
    console.log(person);
 
var person = {
    name: "bob",        //属性名key可以不使用字符串也可以使用,最终会同意转成字符串
    "age": 12
}
console.log(person, person.name, person.age)
对象属性有两种寻址方式:
name=person.lastname;
name=person["lastname"];name = person.fullName();
如果你要访问 person 对象的 fullName 属性,它将作为一个定义函数的字符串返回:
name = person.fullName;
任何对象均有属性constructor,该属性返回对象的构造函数(非字符串). 因此可以通过constructor属性来判断对象是否为数组.
function isArray(myArray) {
    return myArray.constructor.toString().indexOf("Array") > -1;
}
 
变量的存储方式:
JS变量的声明通过var name=value;形式(使用任意类型)
 
变量的作用域:
向未声明的 JavaScript 变量分配值
如果您把值赋给尚未声明的变量,该变量将被自动作为 window 的一个属性。
这条语句:carname="Volvo";    //将声明 window 的一个属性 carname。
非严格模式下给未声明变量赋值创建的全局变量,是全局对象的可配置属性,可以删除。
var var1 = 1; // 不可配置全局属性
var2 = 2; // 没有使用 var 声明,可配置全局属性
console.log(this.var1); // 1
console.log(window.var1); // 1
delete var1; // false 无法删除
console.log(var1); //1
delete var2; 
console.log(delete var2); // true
onsole.log(var2); // 已经删除 报错变量未定义
 
如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
以下实例中 carName 在函数内,但是为全局变量。
func(); //func()必须执行才会创建carName全局变量,因此打印语句必须放在func()后(在 func() 被第一次调用之前, carName 变量是不存在的即 undefined。func() 被调用过之后,carName成为全局变量。)
console.log(carName);    //此处可调用carName,此处可使用 window.carName
function func(){
    carName = 'vava';
    console.log(carName);
}
注:在 HTML 中, 全局变量是 window 对象: 所有数据变量都属于 window 对象。
 
重新声明 JavaScript 变量
如果重新声明 JavaScript 变量,该变量的值不会丢失:
在以下两条语句执行后,变量 carname 的值依然是 "Volvo":
var carname="Volvo"; 
var carname;
但如果是重新定义变量(即声明+赋值)则变量的值和类型均为最后语句定义的.
var carname="Volvo"; 
var carname=123;    //carname值为123
 
ES6 中的 let 关键字(与var关键字的区别)
let 允许你声明一个作用域被限制在块级中的变量、语句或者表达式。与var关键字不同的是,它声明的变量只能是全局或者整个函数块的。
let 语法:
let var1 [= value1] [, var2 [= value2]] [, ..., varN [= valueN]];
let 声明的变量只在其声明的块或子块中可用,这一点,与 var 相似。二者之间最主要的区别在于 var 声明的变量的作用域是整个封闭函数。
let 和 var 的区别代码实例:
function varTest() {
  var x = 1;
  if (true) {
    var x = "123"; // x变量变了(注意此处的x作用范围并不只是if块内而是整个函数)
    console.log(x); // 123
  }
  console.log(x); // 123
}
 
function letTest() {
  let x = 1;
  if (true) {
    let x = 2; // 不同的变量(let定义的x作用范围为if块内)
    console.log(x); // 2
  }
  console.log(x); // 1
}
 
HTML事件:
方式1:HTML 事件属性可以直接执行 JavaScript 代码:
不推荐使用 HTML 元素中可以添加事件属性 的方式来添加属性。(不符合高内聚低耦合原则)
<button onclick="getElementById('demo').innerHTML=Date()">现在的时间是?</button>
<button onclick="this.innerHTML=Date()">现在的时间是?</button>        //修改自身元素的值
方式2:HTML 事件属性可以调用 JavaScript 函数:
<button onclick="displayDate()">现在的时间是?</button>
方式3:添加事件监听器
注意:在为元素添加事件句柄或者删除元素事件句柄的过程中,不要将 event 参数设置为 onclick,而必须写成 click,去掉事件名称中的 on 即可。
添加事件句柄实例:
<input id="test" type="button" value="提交"/>
<script>
window.onload = function(){
    var test = document.getElementById("test");   
    test.addEventListener("click",myfun2);   
    test.addEventListener("click",myfun1);
}
function myfun1(){  
    alert("你好1");
}
function myfun2(){ 
    alert("你好2");
}
</script>
 
JS字符串:
字符串写在单引号或双引号中
可以在字符串添加转义字符来使用引号:
var x = 'It\'s alright';
var y = "He is called \"Johnny\"
可以使用索引位置来访问字符串中的每个字符:carname[7]
字符串可以是对象:
var x = "John"; //原始值即字面值
var y = new String("John"); //对象
typeof x // 返回 String
typeof y // 返回 Object
x.length
注:不要创建 String 对象。它会拖慢执行速度,并可能产生其他副作用:x===y返回false
字符串分行,可以在双引号中插入\,或每行使用一对“”.
 
==与===的区别:(对应的还有!=与!==)
1、对于 string、number 等基础类型,== 和 === 是有区别的
a)不同类型间比较,== 之比较 "转化成同一类型后的值" 看 "值" 是否相等,=== 如果类型不同,其结果就是不等。
 b)同类型比较,直接进行 "值" 比较,两者结果一样。
2、对于 Array,Object 等高级类型,== 和 === 是没有区别的
进行 "指针地址" 比较
3、基础类型与高级类型,== 和 === 是有区别的
a)对于 ==,将高级转化为基础类型,进行 "值" 比较
b)因为类型不同,=== 结果为 false
 
变量转成布尔值:
其他数据类型转换为布尔类型的规则: null、undefined、0、NaN、空字符串转换为false,其他(object、非空字符串等)转化为 true
逻辑运算:
1、逻辑与&&
JavaScript 中逻辑与和其他语言不太一样,如果第一个操作数是 true(或者能够转为 true),计算结果就是第二个操作数,如果第一个操作数是 false,结果就是 false(短路计算),对于一些特殊数值不遵循以上规则。(个人理解为:如果运算的第一个操作数为true,则返回第二个操作数,反之则返回第一个操作数)
2、逻辑或||
如果第一个操作数不是 false,结果就是第一个操作数,否则结果是第二个操作数。如果第一个操作数能够转为 true,结果就是第一个操作数(个人理解为:如果运算的第一个操作数为 true,则返回第一个操作数,反之则返回第二个操作数)
&与|均为正常的位运算符.
 
条件表达式:
if(){
}
else if(){
}
else{
}
优化if语句的方法:
const condition = 2
let obj = {
  '1' : () => { document.write(1) },    //ES6引入箭头函数,省略函数名直接通过()调用
  '2' : () => { document.write(2) },
  '3' : () => { document.write(3) },
}
obj[condition]()
switch语句:
switch 中 case的判断是===的判断,即数据类型和值的双重判断,这点要注意。case语句后记得加break
另外switch的判断条件可以是String 、Number、Boolean、char、枚举、null、undefined
 
箭头函数:(有待详细了解)
arr.sort((x, y) => { return x-y});    //对数组从小到大排序,传入自定义的比较函数
详见:
 
JavaScript里的循环方法:forEach,for-in,for-of(for循环与C++等完全类似)
for-in一般用于遍历对象的属性;for-of可以遍历生成器
var person={fname:"John",lname:"Doe",age:25}; 
for (x in person) // x 为属性名
{
    txt=txt + person[x];
}
注意:虽然for-in也能遍历数组,但与for遍历是有区别的
for...in 循环会自动跳过那些没被赋值的元素,而 for 循环则不会,它会显示出 undefined。
JS中的break 标签名详见:https://www.runoob.com/js/js-break.html(使得控制外层循环更遍历)
 
正则表达式:
语法:/正则表达式主体/修饰符(可选)
objRegExp.test(str)           //判断字符串str是否满足正则式objRegExp,满足返回true,否则false.
/*校验电话码格式 */
function isTelCode(str) {
    var reg= /^( (0\d{2,3}-\d{7,8}) | (1[3584]\d{9}) )$/;
    return reg.test(str);
}
解析:
(a|b|c)表示a、b、c任选一项均可;即 满足(0\d{2,3}-\d{7,8}) 或(1[3584]\d{9}) 均可
^()表示以什么开头;()$表示以什么结尾
0就是数字0;\d{2,3}表示数字(\d)至少有2个至多有3个;-表示短横线;\d{7,8}表示数字至少有7个至多有8个
1就是数字1;[3584]表示第2个数字必须是3、5、8、4中的一个;\d{9}表示连续9个数字.
 
/*校验邮件地址是否合法 */
function IsEmail(str) {
 var reg=/^\w+@[a-zA-Z0-9]{2,10}(?:\.[a-z]{2,4}){1,3}$/;
 return reg.test(str);
}
解析:
\w+表示单词字符(\w)至少有1个;[a-zA-Z0-9]{2,10}表示2到10个字母或数字的串;
(?:\.[a-z]{2,4}){1,3}表示1到3个匹配.[a-z]{2,4}的串.
"?=n" 匹配任何其后紧接指定字符串 n 的字符串
(?:x) 匹配 'x' 但是不记住匹配项。这种叫作非捕获括号,使得你能够定义为与正则表达式运算符一起使用的子表达式。来看示例表达式 /(?:foo){1,2}/。如果表达式是 /foo{1,2}/,{1,2}将只对 ‘foo’ 的最后一个字符 ’o‘ 生效。如果使用非捕获括号,则{1,2}会匹配整个 ‘foo’ 单词
 
 
JS代码的解析机制:涉及“变量提升”概念(变量提升:函数声明和变量声明总是会被解释器悄悄地被"提升"到方法体的最顶部。)
注:var定义的变量才存在变量提升,let和const定义的变量必须先声明再使用.
JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。
示例1:
x = 5; // 变量 x 设置为 5
elem = document.getElementById("demo"); // 查找元素 
elem.innerHTML = x; // 在元素中显示 x
var x; // 声明 x
示例2:
JavaScript 只有声明的变量会提升,初始化的不会。
var x = 5; // 初始化 x
elem = document.getElementById("demo"); // 查找元素 
elem.innerHTML = x + " " + y; // 显示 x 和 y
var y = 7; // 初始化 y
解析:y 输出了 undefined,这是因为变量声明 (var y) 提升了,但是初始化(y = 7) 并不会提升,所以 y 变量是一个未定义的变量。
示例3:
var getName=function(){
  console.log(2);
}
function getName(){
  console.log(1);
}
getName();
//结果为2
解析:可能会有人觉得最后输出的结果是 1。但是 getName 是一个变量,因此这个变量的声明也将提升到顶部,而变量的赋值依然保留在原来的位置。需要注意的是,函数优先,虽然函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。
//函数、变量声明提升后
function getName(){ //函数声明提升到顶部
  console.log(1);
}
var getName; //变量声明提升
getName = function(){ //变量赋值依然保留在原来的位置
  console.log(2);
}
getName(); // 最终输出:2
 
函数提升优先级高于变量提升。函数提升解释了“为什么可以函数调用在前,函数声明在后”
js中的变量搜索顺序:找变量时,先找局部变量,如果没有局部变量;再找全局变量。
注:JavaScript 严格模式(strict mode)不允许使用未声明的变量。(严格模式通过在脚本或函数的头部添加 "use strict"; 表达式来声明。)
推荐实际写代码中先开始声明再初始化使用。
 
JS浮点数的精度问题:
JavaScript 中的所有数据都是以 64 位浮点型数据(float) 来存储。
所有的编程语言,包括 JavaScript,对浮点型数据的精确度都很难确定:
var x = 0.1;
var y = 0.2;
var z = x + y // z 的结果为 0.3
if (z == 0.3) // 返回 false
解决办法:var z = (x * 10 + y * 10) / 10; // z 的结果为 0.3
最好是通过big.js等库将浮点数装换成字符串来比较.
 
代码块作用域:
在每个代码块中 JavaScript 不会创建一个新的作用域,一般各个代码块的作用域都是全局的。
以下代码的的变量 i 返回 10,而不是 undefined:
实例:
for (var i = 0; i < 10; i++) {
    var j=100;
}
console.log(i, j);    //10,100
注:代码块的作用域是全局的,但函数中的变量是局部的(类似于python)
但可以借助let关键字来限制变量的作用域在代码块中:
 
const 关键字
const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改
const定义常量与使用let 定义的变量相似:
二者都是块级作用域
都不能和它所在作用域内的其他变量或函数拥有相同的名称
两者还有以下两点区别:
const声明的常量必须初始化,而let声明的变量不用
const 定义常量的值不能通过再赋值修改,也不能再次声明。而 let 定义的变量值可以修改。
注:const 的本质: const 定义的变量并非常量,并非不可变,它定义了一个常量引用一个值。使用 const 定义的对象或者数组,其实是可变的。(但是我们不能对常量对象重新赋值)
 
显式函数绑定
在 JavaScript 中函数也是对象,对象则有方法,apply 和 call 就是函数对象的方法。这两个方法异常强大,他们允许切换函数执行的上下文环境(context),即 this 绑定的对象。
在下面实例中,当我们使用 person2 作为参数来调用 person1.fullName 方法时, this 将指向 person2, 即便它是 person1 的方法:
实例
var person1 = {
  fullName: function() {
    return this.firstName + " " + this.lastName;
  }
}
var person2 = {
  firstName:"John",
  lastName: "Doe",
}
person1.fullName.call(person2); // 返回 "John Doe"
 
void()仅仅是代表不返回任何值,但是括号内的表达式还是要运行,如:void(alert("Wornning!"))
 
 
JS中模块化编程(require.js库:require函数和define函数)
注:当依赖多个模块时,多模块加载是异步的,require函数中的回调函数的执行是同步的。
require函数是加载依赖模块,然后执行callback;而define函数是定义能在require中加载的模块
require加载的模块默认与当前目录在同一目录下且模块名即文件名.
详见:
 
 
同一个Web工程中,主入口导入了需要的js文件,其他子html无需再导入可以直接使用该js中定义的东西.
eg:index.html加载了a.js文件,而a.js文件中自定义了命令hello,则index.html跳转的a.html无需加载a.js就能直接使用该命令hello.
 
 
ng-repeat-strart和ng-repeat-end可以控制循环体的范围,而ng-repeat无法控制循环体的范围. eg:
<!-- angular test -->
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<title>angular test</title>
</head>
<body ng-app="myApp", ng-controller="UserCtrl">
 
    <div class="uk-panel" ng-controller="UserCtrl">
            <ul class="uk-list uk-list-striped">
                <li ng-repeat-start="user in users">
                    {{user.name}}
                </li>
                <p>{{user.name}}</p>
                <li ng-repeat-end>
                    {{user.email}}
                </li>
            </ul>
            <!-- 区别于以下 -->
            <!-- <ul ng-repeat="user in users" class="uk-list uk-list-striped">
                    <li>{{user.name}}</li>
                    <li>{{user.email}}</li>
            </ul> -->
    </div>
 
<script src='https://cdn.staticfile.org/angular.js/1.5.8/angular.min.js'></script>
<script>
    var myApp = angular.module('myApp', []);
    myApp.controller('UserCtrl', ['$scope', function($scope){
            $scope.users = [
                {
                    name:'张三',
                    email:'zhangsan@gmail.com'
                },
                {
                    name:'李四',
                    email:'lisi@123.com'
                },
                {
                    name:'王五',
                    email:'wangwu@qq.com'
                }
            ];
    }]);
</script>
</body>
</html>

 

 
console.log()打印修改前后的对象/数组,“结果”相同的问题?
原因:浏览器console.log()打印的是对象的引用,点开对象变量后展示的是该对象/数组的属性,因此前后展示的结果相同。
解决办法:直接打印字符串:console.log(JSON.stringify(rabbit));
实例:
arr.splice(0, 0, "haah"); //当第二个参数num=0时,则在第一个参数的位置处添加一个元素
arr.splice(0, 0, 100);  
console.log(arr) //两处打印尽然一样?
arr.splice(1,2) //当第二个参数num>0时,则在第一个参数的位置处删除元素
console.log(arr)
for(var i=0;i<2;i++)
{
    arr.splice(0, 0, i);  
    console.log(arr)
}
console.log(arr)
 
常见console调试方法:
 
打开页面和刷新页面的方法:
用window.open()打开新页面,但是用window.location.href="" 却是在原窗口打开的. 
 
 
运行js文件的几种方式:
在html文件中引入;
在chrome调试器中执行(以语句形式或snippets形式执行)
单独运行js文件的方法:控制台:node xx.js
在一个js文件中引入另一个js文件的方法:http://www.fly63.com/article/detial/1183
 
每张网页都有Document对象,document对象不属于js而是html,但Js能通过document提供的方法操作页面。
 
 

window.setTimeout() 和 window.setInterval() 区别:

setTimeout 在执行时,是在载入后延迟指定时间后,去执行一次表达式,仅执行一次

setInterval在执行时,它从载入后,每隔指定的时间就执行一次表达式。

 
"use strict"; //指明代码在严格条件下执行.不允许未定义先使用等情况发生.
 
function定义的对象有一个prototype属性,prototype允许我们在创建对象之后来改变对象或类的行为,并且这些通过prototype属性添加的字段或方法所有对象实例是共享的。
eg:
var storage = function () {
        var storage = window.cookieStorage;
        if (typeof(Storage) !== "undefined") {
            storage = window.sessionStorage;
        }
        this.storage = storage;
        this.cookieStorage = cookieStorage;
    };
    //js中function定义的对象有一个prototype属性; prototype允许我们在创建对象之后来改变对象或类的行为,并且这些通过prototype属性添加的字段或方法所有对象实例是共享的。
    storage.prototype.add = function (key, value, ttl) {
        var storage = this.storage;
        if (typeof(value) === "object") {
            value = JSON.stringify(value);
        }
        storage.setItem(key, value, ttl);
    };

 

遍历DOM元素:
            var nodes = document.all;
            for (var i = 0; i < nodes.length; i++) {
                var o = nodes[i];
                console.log(o.tagName + ":" + o.id);
            }    
获取dom元素的两种方式:
console.log(document.getElementById('person1'))
console.log($('#person1').get(0)) //id是#person1,class是.person1    需要引入jQuery库
遍历字典:
for (var key in nodes) {
    console.log(nodes[key])
}
遍历数组效率最高的方式:就是普通的遍历法
for(var i=0, len=arr.length; i<len; i++){}
 
删除数组元素:
function delArrVal(arr,val){ //查找数组中的某个值并全部删除 第一个参数是查找的数组 第二个参数是删除的值
      for(let i=0;i<arr.length;i++){
        if(arr[i]==val){
          arr.splice(i,1)
          i--;
        } 
      } 
      return arr;
    } 

 

undefined和null作为条件表达式时均是false
//判断undefine
var exp = undefined;
if (typeof(exp) == "undefined")
{
    alert("undefined");
}
 
//判断null
var exp = null;
if (!exp && typeof(exp)!="undefined" && exp!=0)
{
    alert("is null");
} 
 
获取字典或对象的keys:Object.keys(dict)
 
判断对象是否有方法:直接 if(对象.方法)即可
 
获取鼠标位置:
 
如何保证页面元素加载完再执行js代码:
 
事件即可以在捕获阶段执行:即从父元素到子元素的定位过程;也可以在冒泡阶段执行:即从子元素到父元素传播的过程. stopPropagation函数可以阻止事件流(包括捕获/冒泡,这样子元素或父元素就不会触发该事件)
 
 // 获取选中的的标注文字及range
            $scope.selectedLabelWordRange = {
                range: '',
                text: ''
            };
            $scope.selectLabelWords = function () {
                if (window.getSelection) {
                    var range = window.getSelection().getRangeAt(0);
                    $scope.selectedLabelWordRange.range = range;
                    $scope.selectedLabelWordRange.text = window.getSelection().toString(); //获取选中范围的文字内容
                    console.log("selected text: " + window.getSelection().toString());
                }
            }        
 //获取选中范围的坐标:
 var range = window.getSelection().getRangeAt(0);
 var rect = range.getBoundingClientRect();
 var x = rect.left, y = box.top;
 
阻止选中某个区域的文本:(建议采用css方法,然后利用jQuery的addClass方法添加样式)
entityTypeEle.onselectstart = function(){return false;};    //该方法有局限性,只有当鼠标焦点在该元素内才有效;但鼠标在外部仍可以拖动选择该文本.
 
利用Range获取某小段文本的实际坐标位置:
 var range = new Range();
    range.setStart(text.firstChild, 0); //表示第0个子节点,而非第0个字符
    range.setEnd(text.firstChild, text.textContent.length); //表示第1个子节点,而非第1个字符
    /* 注意setStart和setEnd的参数1若为非文本节点(文本节点eg:span的firstChild;span并不是文本节点), 则参数2表示的是参数1元素的第几个字节点
        参数1若为文本节点,则参数2表示的是文本节点的第几个字符. 这样即可获取文本中某段文字的坐标位置.
    */
    console.log(range.getBoundingClientRect()) //获取range的clientRect
    document.getSelection().addRange(range); //将range加入选中区域,这样即可以看到选中
    console.log(document.getSelection().getRangeAt(0));

 

在JS中未使用var声明的变量是全局变量,在当前js文件的任何位置均可直接使用;使用var声明的变量是局部变量,只限于当前代码块中使用.
 
<p>haha</p>        其中文本是p元素的子元素
 
==============================    JS基础    ===============================
JS中调用setTimeout函数的两种方式:
setTimeout(要执行的代码, 等待的毫秒数)   //参数1字符串
setTimeout(JavaScript 函数, 等待的毫秒数)
因此定时调用一个函数有两种方式:
方法1:setTimeout("func()", 1);
方法2:setTimeout(func, 1);
在函数中调用setTimeout,然后再设置该函数为setTimeout即可实现每隔一定事件重复调用某函数.
在等待事件内取消某定时任务的执行:
 id = setTimeout(func,  1);
clearTimeout(id); 
clearTimeout的作用:可以避免定时任务的累积,保证队列中至多只有一个定时任务. eg:
function moveElement(elementID, final_x, final_y, interval) {
    if (!document.getElementById) return false;
    if (!document.getElementById(elementID)) return false;
    var elem = document.getElementById(elementID);
    if (elem.movement) { //保证始终只有一个定时任务执行.
        clearTimeout(elem.movement);
    }
    var xpos = parseInt(elem.style.left);
    var ypos = parseInt(elem.style.top);
    if(xpos == final_x && ypos == final_y){
        return true;
    }
    if(xpos < final_x){
        xpos++;
    }
    if(xpos > final_x){
        xpos--;
    }
    if(ypos < final_y){
        ypos++;
    }
    if(ypos > final_y){
        ypos--;
    }
    elem.style.left = xpos + "px";
    elem.style.top = ypos + "px";
    var repeat = "moveElement('" + elementID + "'," + final_x + "," + final_y + "," + interval +")";
    elem.movement = setTimeout(repeat, interval); //为元素创建属性
}
 
posted @ 2020-03-04 10:26  Coding练习生  阅读(163)  评论(0编辑  收藏  举报