Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

js笔记收录(1) #6

Open
msforest opened this issue Dec 26, 2016 · 6 comments
Open

js笔记收录(1) #6

msforest opened this issue Dec 26, 2016 · 6 comments

Comments

@msforest
Copy link
Owner

msforest commented Dec 26, 2016

  1. call/apply/slice/splice/substr
  2. delete操作符
  3. setTimeout/setInterval中的this
  4. javascript-garden
  5. attribute & property(javascript.info)
  6. js 运算符的优先级
  7. js 相等(==)运算符深入解析


一直想整理关于js的一些特殊方法,eg:call/apply/slice/splice/substr...

call/apply

call/apply:可以简单理解为调用/应用,属于Function.prototype的一个方法,所以每个Function对象实例都有call/apply属性,两者作用效果是相同的,只是用法不同
foo.call(this, arg1,arg2,arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)

  • this表示执行foo方法的上下文相关对象
  • arg1,arg2,arg3表示传递给foo方法的参数

使用apply时,把参数当做一个整理传递;而使用call时,把参数分开,一个一个地传递;

call/apply:表示在指定作用域中执行调用函数(函数已执行)
bind: 表示给调用函数指定作用域(函数未执行)


callee/caller

  • callee 是arguments的一个属性,是指针类型,指向拥有arguments对象的函数
  • caller 是函数对象的一个属性,通过函数名调用,如FunctionName.caller,指向调用当前函数的函数的引用
    callee
//使用callee前
function test(x){
    if (x<=1) {
    	return 1;
    } else{
    	return x*test(x-1);
    };
};
//使用callee后
function test(x){
    if (x<=1) {
    	return 1;
    }else{
    	return x*arguments.callee(x-1);
    };
};

根据callee的定义,可以看出来callee是arguments对象的一个属性,指向arguments对象的函数,这个函数就是test(test=arguments.callee)
caller

function a(){
	b();
};
function b(){
	alert(b.caller);
};
a(); //结果就是弹出函数a和内容

函数b的属性caller调用当前函数b的函数引用a(就是指向当前函数b的父函数a),所以结果就是弹出 function a(){ b();};


splice

可以表示截取、替换、删除的意思,这里指数组。该方法会改变原始数组
splice是一个全能型的方法,通过参数的个数来实现不同的操作。

  • 删除:两个参数,如下:
    arr.splice(2,1)表示从数组下标为2开始向后删除一项,即删除下标为2的指定项
  • 插入:(2+n)个参数,如下:
    arr.splice(2,0,'add1','add2')表示从数组下标为2的指定项后面添加,第二个参数必须为0
  • 替换:(2+n)个参数,如下:
    arr.splice(2,1,'replace')表示从数组下标为2的指定项开始,后面的第一个指定项替换为replace字符串

slice/substr/substring

都表示截取的意思

  • slice() slice(i,[j])既可以表示字符串截取也可以表示数组截取,不改变原始内容,返回结果为从ij指定的内容,如果没有j,表示从i到末尾
  • substr() substr(start,length)表示字符串截取,不改变原始内容,如果没有第二个参数,表示截取到内容末尾
  • substring() substring(start,end)表示字符串截取,不改变原始内容,如果没有第二个参数,表示截取到内容末尾

push/pop/shift/unshift

这几个方法构成数据结构的堆栈和队列;push()从末尾追加数据,pop()从末尾输出数据,shift()从头部弹出数据,unshift()从头部追加数据。

  • push/pop:构成堆栈结构,遵循LIFO原则,即后进先出
  • unshift/push:构成队列结构,遵循FIFO原则,即先进先出
  • shift/pop:构成反队列结构,也是先进先出
@msforest
Copy link
Owner Author

msforest commented Jan 8, 2017

delete操作符只能对实例的属性和方法有效,对原型上的属性和方法删除无效

es5引入了几个方法来防止对对象的修改:

  1. 防止扩展
    禁止为对象添加属性和方法,但已存在的属性和方法是可以被修改和删除
  2. 密封
    类似‘防止扩展’,而且禁止为对象删除已存在的属性和方法
  3. 冻结
    类似‘密封’,而且禁止为对象修改已存在的属性和方法(所有字段均只读)
//防止扩展
var person = {name:'nico'}
Object.preventExtensions(person);
console.log(Object.isExtensible(person));  //false
person.age = 22;  //正常情况下,悄悄失败,严格模式下会抛出错误

//密封
Object.seal(person);
console.log(Object.isExtensible(person));  //false
console.log(Object.isSealed(person));  //true
delete person.name;  //正常情况下,悄悄失败,严格模式下会抛出错误
person.age = 22;  //同上

//冻结
Object.freeze(person);
console.log(Object.isExtensible(person));  //false
console.log(Object.isSealed(person));  //true
console.log(Ojbect.isFrozen(person));  //true
person.name = 'welcome';  //正常情况下,悄悄失败,严格模式下会抛出错误
person.age = 22;  //同上
delete person.name;  //同上

@msforest
Copy link
Owner Author

msforest commented Mar 13, 2017


setTimeout/setInterval中的this

var name = 'some';
var adding = {
    name: 'adding',
    say: function(){ alert('I\'m ' + this.name); }
};
adding.say();  //I'm adding
setTimeout(adding.say, 1000);   //I'm some
setInterval(adding.say, 1000);   //I'm some

setTimeout(function(){
    adding.say();  //I'm adding
}, 1000);
setInterval(function(){
    adding.say();  //I'm adding
}, 1000);

2

在setTimeout中传入的不是函数时,this则指向当前对象;
当在setTimeout中传入的参数为函数时,函数内部的this才会指向window对象。
可以通过bind来绑定this值

var name = 'some';
var adding = {
    name: 'adding',
    say: function(){ setTimeout(console.log('i\'m ' + this.name), 1000); }
};
adding.say(); // i'm adding
var adding = {
    name: 'adding',
    say: function(){ setTimeout(function(){
         console.log('i\'m ' + this.name); 
     },1000)
}
};
adding.say(); // i'm some

可以通过保存this值或bind方法来得到我们期望的this
如果使用call或apply方法来代替bind方法,得到的结果也是正确的,但是call方法会在调用之后立即执行,那样也就没有了延时的效果,定时器也就没有用了

setTimeout/setInterval方法的第三个参数及之后的参数都作为function函数的参数

var timeoutID = scope.setTimeout(function[, delay, param1, param2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);

setTimeout

@msforest
Copy link
Owner Author

msforest commented Jun 8, 2017

避免使用空位数组
new Array(3) 构造函数会返回一个 length 属性被设置为此参数的空数组。需要特别注意的是,此时只有 length 属性被设置,真正的数组并没有生成。
new Array(3).join('#') 将会返回 ##
javascript-garden
array 空位

@msforest
Copy link
Owner Author

msforest commented Jul 5, 2017

attribute & property

attribute是对于html而言的特性,property是对于dom节点而言的;对于标准的html特性,可以通过点操作符来获取值,而非标准的html特性,需要通过方法来获取值,比如getAttribute
attribute & property这篇文章介绍了两者的共同点和不同点,如通过DOM对象的点操作符获取非标准的html特性,值会等于undefined

<body id="test" something="non-standard">
  <script>
    alert(document.body.id); // test
    // non-standard attribute does not yield a property
    alert(document.body.something); // undefined
  </script>
</body>

对于标准的html特性的更新,对应的dom获取的property值也会相应更新

<input>

<script>
  let input = document.querySelector('input');

  // attribute => property
  input.setAttribute('id', 'id');
  alert(input.id); // id (updated)

  // property => attribute
  input.id = 'newId';
  alert(input.getAttribute('id')); // newId (updated)
</script>

Butinputvalue值不会同步更新

<input>

<script>
  let input = document.querySelector('input');

  // attribute => property
  input.setAttribute('value', 'text');
  alert(input.value); // text

  // NOT property => attribute
  input.value = 'newValue';
  alert(input.getAttribute('value')); // text (not updated!)
</script>

对于一些非标准的attribute,一般使用data-*前缀,这样就可以通过DOM对象的点操作符来获取/更新值,如

<div id="order" class="order" data-order-state="new">
  A new order.
</div>

<script>
  // read
  alert(order.dataset.orderState); // new

  // modify
  order.dataset.orderState = "pending"; // (*)
</script>

top

@msforest
Copy link
Owner Author

msforest commented Feb 25, 2018

javascript 运算符的优先级

MDN Operator precedence

Precedence Operator type Associativity Individual operators
20 Grouping n/a ( … )
19 Member Access left-to-right … . …
Computed Member Access left-to-right … [ … ]
new (with argument list) n/a new … ( … )
Function Call left-to-right … ( … )
18 new (without argument list) right-to-left new …
17 Postfix Increment n/a … ++
Postfix Decrement … --
16 Logical NOT right-to-left ! …
Bitwise NOT ~ …
Unary Plus + …
Unary Negation - …
Prefix Increment ++ …
Prefix Decrement -- …
typeof typeof …
void void …
delete delete …
await await …
15 Exponentiation right-to-left … ** …
14 Multiplication left-to-right … * …
Division … / …
Remainder … % …
13 Addition left-to-right … + …
Subtraction … - …
12 Bitwise Left Shift left-to-right … << …
Bitwise Right Shift … >> …
Bitwise Unsigned Right Shift … >>> …
11 Less Than left-to-right … < …
Less Than Or Equal … <= …
Greater Than … > …
Greater Than Or Equal … >= …
in … in …
instanceof … instanceof …
10 Equality left-to-right … == …
Inequality … != …
Strict Equality … === …
Strict Inequality … !== …
9 Bitwise AND left-to-right … & …
8 Bitwise XOR left-to-right … ^ …
7 Bitwise OR left-to-right … | …
6 Logical AND left-to-right … && …
5 Logical OR left-to-right … || …
4 Conditional right-to-left … ? … : …
3 Assignment right-to-left … = …
… += …
… -= …
… **= …
… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …
2 yield right-to-left yield …
yield* yield* …
1 Comma / Sequence left-to-right … , …

top

@msforest
Copy link
Owner Author

msforest commented Feb 27, 2018

相等(==)深入解析

ecma262 ==

The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:

  1. If Type(x) is the same as Type(y), then
    1. If Type(x) is Undefined, return true.
    2. If Type(x) is Null, return true.
    3. If Type(x) is Number, then
      1. If x is NaN, return false.
      2. If y is NaN, return false.
      3. If x is the same Number value as y, return true.
      4. If x is +0 and y is −0, return true.
      5. If x is −0 and y is +0, return true.
      6. Return false.
    4. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions). Otherwise, return false.
    5. If Type(x) is Boolean, return true if x and y are both true or both false. Otherwise, return false.
    6. Return true if x and y refer to the same object. Otherwise, return false.
  2. If x is null and y is undefined, return true.
  3. If x is undefined and y is null, return true.
  4. If Type(x) is Number and Type(y) is String,
    return the result of the comparison x == ToNumber(y).
  5. If Type(x) is String and Type(y) is Number,
    return the result of the comparison ToNumber(x) == y.
  6. If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.
  7. If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
  8. If Type(x) is either String or Number and Type(y) is Object,
    return the result of the comparison x == ToPrimitive(y).
  9. If Type(x) is Object and Type(y) is either String or Number,
    return the result of the comparison ToPrimitive(x) == y.
  10. Return false.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant