var myObject = {
value: 0,
increase: function(inc) { // 此处不能用 => 来声明函数
console.log(this); // myObject本身
this.value += typeof inc==='number'?inc:1;
}
}
console.log(myObject.value); // 0
myObject.increase();
console.log(myObject.value); // 1
myObject.increase(33);
console.log(myObject.value); // 34
这种通过this调用上下文对象的方法称为公共方法。this和上下文之间的绑定发生在它调用的时候。这种超级延迟的绑定使得this可以高度复用。
当一个函数并非一个对象的属性的时候,那么他就被当作一个函数来调用,此时
'use strict';
var myObject = {
value: 0,
increment: function (inc){
this.value+= typeof inc==="number"?inc:1;
}
}
let add = (a,b) => a+b;
myObject.double = function (){
var that = this; // 此处this指向函数本身
var helper = function (){
console.log('myObject.double', thar); // 此处this在非严格模式☞全局,严格模式undefined
that.value = add(that.value, that.value)
}
helper()
}
myObject.double();
console.log(myObject);
js语言是一门基于原型继承的语言,可以从其他对象继承属性,该语言是无类型的。这和当前编程语言的主流风格不符合,但是如果你在函数调用之前加上new
的话,那么背地里将会创造一个连接到函数prototype
成员的新对象,同时this会绑定到那个新对象上面。同时new
前缀也会改变return
语句的行为。
'use strict';
var Quo = function (str){
this.status = str;
}
Quo.prototype.get_status = function (){
return this.status;
}
var myQuo = new Quo('confused');
console.log(myQuo.get_status()); // confused
一个函数创造的目的就是为了结合new前缀来调用,那么我们称之为构造函数,但是JavaScript语言精粹并不推荐这种构造方法。
因为js是一门函数式面向对象编程语言,所以函数拥有方法。 apply方法让我们构建一个参数数组传递给调用函数,他也允许我们选择this的值,apply接受2个参数,第一个是要绑定this的值,第二个就是一个参数数组。
doms = document.querySelectorAll('div');
Array.prototype.slice.apply(doms).map(e=> e.id); // doms是没有map的方法,经过apply后拥有了map方法。
var try_it = function (args){
try {
console.log(whatever); // ReferenceError sdsd is not defined
} catch (e) {
console.log(e.name+" ",e.message);
}
}
try_it();
console.log(console);
并不会因为报错就不执行之后的代码,这体验还是不错的。
为什么要这样呢,之前一直是用css的来写这种收缩动画,直到后来,css越来越大(压缩后200kb),我抑郁了。yes i promise you can use let
instead of var
in js everywhere.
const fade = (dom) => {
let level = 1;
const step = () => {
dom.style.backgroundColor = `rgb(255,255,${level})`;
if (level < 255) {
level += 11;
setTimeout(step, 100);
} else {
level = 1;
setTimeout(step, 100);
}
};
step();
};
fade(document.body);
arguments
获得参数'use strict';
const a = function () {
console.log(arguments);
};
const b = () => {
console.log(arguments);
};
a(1, 2, 3);
b(1, 2, 3);
var serial_maker = function(){
// 返回一个用来产生唯一字符串的对象
// 位移字符串由:前缀+序列号
// 这包括一个设置前缀的方法,一个设置序列号的方法
// 和一个产生位移字符串的gensym的方法
var prefix = ' ';
var seq = 0;
return {
set_prifex: function(p) {
prefix = String(p);
},
set_seq: function (s){
seq = s;
},
gensym: function(){
var result = prefix+seq;
seq += 1;
return result;
}
}
}
var seqer = serial_maker();
seqer.set_prifex("Q");
seqer.set_seq(1111)
var unique = seqer.gensym();
console.log(unique); // Q1000
返回this而不是undefined,这样就可以实现jquery的链式调用。这和函数式编程又有所不同。另一个返回的是data数组。用es6的class手写一个jQuery,实现链式调用,
class TQuery {
constructor(tArg) {
this.version = 0.1;
this.author = 'pengliheng';
this.DOM = [...document.querySelectorAll(tArg)]
}
css (attr, value) {
this.DOM.forEach(dom=> dom.style[attr] = value )
return this;
}
}
window.$ = tArg => new TQuery(tArg);
实现一个最简单版本的jQuery链式调用,同时改变背景颜色,字体颜色,字体大小。
$('body').css('background','pink').css('color','red').css('font-size','50px');
链式调用的效率,由于jQuery返回的是整个this.所以他是低效的。
//耗时:104ms
for (let i = 0; i < 10000; i++) {
$('div');
}
//耗时:4.7ms
for (let i = 0; i < 10000; i++) {
document.querySelector('div');
}
const myMammal = {
name: 'Herb the Mammal',
getName() {
return this.name;
},
says() {
return this.saying || '';
},
};
const myCat = Object.create(myMammal);
myCat.name = 'mimi';
myCat.saying = 'meow';
myCat.purr = (n) => {
let i;
let s = '';
for (i = 0; i < n; i += 1) {
if (s) {
s += '-';
}
s += 'r';
}
return s;
};
myCat.getName = () => `${this.says} ${this.name} ${this.says}`;
console.log(myCat, myMammal);
到目前为止,我们所看到的继承模式一个弱点就是没有隐私,因为所有属性都会被继承,即可见
首先想到的自然是typeof
,但他的que缺陷也是显而易见的
细想一下,为何不用constructor
,,看图,没错,识别了[]和{},但是null和NaN,undefined报错,
改良一下的最终解决方案式,唯一美中不足的是,不能识别undefined,请再配合isNaN一起使用,用来识别number和NaN的区别
顺便一提,call
和apply
的效果是一样的
Object.prototype.toString.call(123) // [object Number]
Object.prototype.toString.apply(123) // [object Number]
==
,!=
, 为了不出bug,==
应该禁止使用'' == '0' // false
0 == '' // true
0 == '0' // true
with
, JavaScript提供了一个with语句,本意是快捷访问对象的属性,不过结果不可预料,应该禁止使用。
下面的语句with (object) {
a == b;
}
with 在这门语言的出现,本身影响了JavaScript处理器的速度,他阻断了变量名词法作用域的绑定,他的本意是好的。
eval("myValue = myObject."+a+";")
++
,--
语句,这个也禁止使用,建议用i+=1替换。& and 按位与
| or 按位或
^ xor 按位异或
~ not 按位非
>> 带符号的右位移
>>> 无符号的(用0补足)右位移
<< 左位移
通常用于执行硬件处理,但JavaScript不处理硬件,所以位运算符很慢
function test(){}
var test = function(){}
一个语句不能以function开头,因为官方表示假定单词以function开头被认为是一个funciton语句。可以用如下做法避免他。
(function (){
var hidden_val;
// 这个函数对环境有一些影响,但不会引入新的全局变量
})