js基础

Objects中的属性:

  • 1: Object.keys 和 Object.getOwnPropertyNames: 检索对象中所有的属性名,前一个方法返回所有可枚举的属性名,后一个方法不考虑属性的可枚举性一律返回, 但都不支持Symbol属性,ES6中增加 Object.getOwnPropertySymbols()方法来检索对象中的Symbol属性
  • 2:
//obj instanceof Array == Array[Symbol.hasInstance](obj)

function specailNumber(){}
Object.defineProperty(specailNumber,Symbol.hasInstance,{value:(v)=>(v instanceof Number) && (v >= 1 && v <= 100)})
var two = new Number(2)
    zero = new Number(0)
print(two instanceof specailNumber)
print(zero  instanceof specailNumber)
-------------------------------------------------------------------
let collection = {
    0:"hello",
    1:"world",
    length:2,
    [Symbol.isConcatSpreadable]:true
};
let message = ["HI"].concat(collection);
print(message) //[ 'HI', 'hello', 'world' ]

0 ES5 有5种类型, ES6有6种类型

  • 1: ES5: 字符串型,数字型,布尔型,null,undefined
  • 2 : ES6 + Symbol ,Symbol是原始值,因此调用new Symbol() 会报错. 但是可以 typeof symbol
  • 3: Symbol的描述被存储在内部的[[Description]]属性中,只有当调用Symbol的toString()方法时才可以读这个属性
  • 4: 所有使用可计算属性名的地方,都可以使用Symbol.Object.defineProperty()方法和Object.defineProperties()方法
  • 5: Symbol.for("uid"), 首先在全局Symbol注册表中搜索键为"uid"的Symbol是否存在,存在返回,不存在,创建新的Symbol并返回
let firstname = Symbol("firstname");
//可计算
let person = {
    [firstname]:"Nichols"
};
//将属性设置为只读
Object.defineProperty(person,firstname,{writable:false});
let lastname = Symbol("last name");
Object.defineProperties(person,{
    [lastname]:{
        value:"Zakes",
        writable:false
    }
});
print(person.firstname,person.lastname);

1 箭头函数

  • 1: 没有this,super,arguments和new.target绑定,箭头函数中的 this,super,arguments和new.target这些值由外围最近一层非箭头函数决定,
  • 2: 不能通过new关键字调用, 箭头函数没有[[]Construct]方法,所以不能作为构造函数,如果用了new就会抛出错误.
  • 3: 没有原型,由于不能通过new构造,因而没有构造原型的需求,所以箭头函数不存在prototype这个属性
  • 4: 不可以改变this的绑定,函数内部的this值不可以改变,在函数的生命周期内始终保持一致.
  • 5: 不支持 arguments对象,箭头函数没有arguments绑定,所以你必须通过明明函数和不定参数这两种形式访问函数的参数.
  • 6: 不支持重复的命名参数 无论严格参数还是非严格模式下,箭头函数都不支持重复的命名参数
  • 7: 箭头函数同样也有一个name属性,这与其他函数相同.
  • 8: 箭头函数的设计初衷是: 即用即弃, 箭头函数内的this也不能通过call apply bind来改变.但是可以在箭头函数上调用call apply bind方法,与其他函数不同,箭头函数的this值不会受这些方法的影响
var sum = (num1,num2) => num1+num2;
print(sum.call(null,1,2))
print(sum.apply(null,[1,2]))
var boundSum = sum.bind(null,1,2)
print(boundSum())

2 ES6中尾递归优化: 满足以下条件,尾调用不再创建新的栈帧,而是清除并重用当前栈帧

  • 1: 尾调用不访问当前栈帧的变量(也就是说函数不是一个闭包)
  • 2: 在函数内部,尾调用是最后一条语句
  • 3: 尾调用的结果作为函数值返回

3: js中的对象 普通对象 特异对象 标准对象 内建对象

  • 1: 普通对象(ordinary): 具有js对象所有的默认内部行为
  • 2: 特异对象(exotic) 具有某些与默认行为不符的内部行为
  • 3: 标准对象: ES6规范中定义的对象.Array Date等
  • 4: 内建对象: 脚本开始执行时存在于js执行环境中的对象,所有标准对象都是内建对象.

4: Object.assign and 自有属性的枚举顺序

  • 1: 所有数字按升序排序
  • 2: 所有字符串键按照他们被加入对象的顺序排序
  • 3: 所有symbol键按照他们被加入对象的顺序排序
var obj = {
    a:1,
    0:1,
    c:1,
    2:1,
    b:1,
    1:1
};
obj.d = 1;
print(Object.getOwnPropertyNames(obj).join("")) //012acbd

5: 改变对象的原型 Object.setPrototypeof()

let person = {
    getGreeting(){
        return "hello";
    }
}
let dog = {
    getGreeting(){
        return "woof!";
    }
}
//person prototype
let friend = Object.create(person);
print(friend.getGreeting()); //hello
print(Object.getPrototypeOf(friend) == person); //true
//set prototypeOf dog
Object.setPrototypeOf(friend,dog);
print(friend.getGreeting()) //woof!
print(Object.getPrototypeOf(friend) == dog); //true

6: 简化原型访问的super引用,必须在简写方法的对象中使用Super引用

let person = {
    getGreeting(){
        return "hello";
    }
}
let dog = {
    getGreeting(){
        return "woof!";
    }
}
let friend = {
    getGreeting(){
        //return Object.getPrototypeOf(this).getGreeting.call(this) +" hi!";
        return super.getGreeting() +" hi!";
    }
}

Object.setPrototypeOf(friend,person);
print(friend.getGreeting())
print(Object.getPrototypeOf(friend) === person)

Object.setPrototypeOf(friend,dog);
print(friend.getGreeting())
print(Object.getPrototypeOf(friend) == dog)

7: 使用var let const解构声明变量,则必须提供初始化程序.

  • 1: 如果不使用解构功能,则var let声明不强求提供初始化程序,但是const需要
  • 2: 任何解构表达式尝试读取 null or undefined的属性时都是报错.
  • 3: 读取type的属性并将其存储在变量localType中,let {type:localType,name:localName} = node
  • 4: 可以嵌套读取
let node = {
    type:"Identity",
    name:"foo",
    loc:{
        start:{
            line:1,
            column:1
        },
        end:{
            line:2,
            column:2
        }
    }
}
let {loc :{end}} = node ;
print(end.line,end.column)
let a = 1,
    b = 2 ;
[a,b] = [b,a]
print(a,b) //交换 a,b的值

// 复制数组
let colors = ["red","green","blue"];
let [...clone] = colors
print(clone)
print(colors.join(" "))
print(colors.concat(" "))

//应用场景1
function setCookie(name,value,{secure,path,domain,expire} = {}) //使用解构的话比较清晰

// ES6 之前的模拟 set and map
var set = Object.create(null);
set.foo = true
if(set.foo){
    print("hello")
}
var map = Object.create(null)
map.foo = "bar";
print(map.foo)

// 若引用set, 集合中的弱引用如果是对象的唯一引用,则会被回收并且释放相应内存(不支持原始值,只支持引用类型)

let set = new WeakSet(),
    key = {};
set.add(key);
print(set.has(key)); //true
set.delete(key);
print(set.has(key)); //false
//注意weakset: 不可迭代即不可以使用for..in (2)不能不报露任何迭代器例如keys and values (3)不支持forEach (4) 不支持size属性

// set and map底层都是Object.is判断相等的
 let map = new Map();
map.set("title","Understanding js");
map.set("year",2016)
print(map.get("year"))
print(map.get("title"))
//默认初始化
let map = new Map([["title","Understanding js"],["year",2016]]);
//迭代map (value,key,ownermap) => print ...
map.forEach((v,k) => print(k+" -> "+v))
//使用weak map 存储私有数据
let Person = (function(){
    let privateDate = new WeakMap();
    function Person(name){
        privateDate.set(this,{name:name});
    }
    Person.prototype.getName = function(){
        return privateDate.get(this).name;
    };
    return Person;
}());
var p1 = new Person("shen");
var p2 = new Person("yang");
print(p1.getName())
print(p2.getName())

//新的迭代器: for ..of 循环,展开运算符(...) ,异步编程也可以使用迭代器

//ES5中写迭代器的写法, ES6中增加了 一个生成器对象,他可以让创建迭代器对象变得简单
function createIter(items){
    var i = 0;
    return {
        next : function(){
            var done = (i>=items.length);
            var value = !done ? items[i++] : undefined;
            return {done:done,value:value};
        }
    }
}
var iter = createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())

//生成器是一种返回迭代器的函数,通过function*来表示,函数中会用到新的关键字yield
function*createIter(){
    yield 1;
    yield 2;
    yield 3;
}
function*createIter(items){
    for(let i = 0;i<items.length;i++){
        yield items[i];
    }
}

var iter = createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//生成器对象的方法,
let o = {
    *createIter(items){
        for(let i =0;i<items.length;i++){
            yield items[i];
        }
    }
}
let iter = o.createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())

//由于生成器默认会为Symbol.iterator属性赋值,因此所有通过生成器创建的迭代器都是可迭代对象
//for-of 循环每执行一次都会调用可迭代对象的next方法
//访问默认迭代器
let values = [1,2,3]
let iter = values[Symbol.iterator]();
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//检测对象是否可迭代

//默认开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,者可以变成一个迭代对象
let collection = {
    items:[],
    *[Symbol.iterator](){
        for(let item of this.items){
            yield item;
        }
    }
}
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);

for(let x of collection){
    print(x)
}

// 内建迭代器: entries() values() keys()
let data = new Map([["title","understanding ES6"],["format","ebook"]]);
for(let [key,value] of data){
    print(key+" -> "+value);
}

//第二次调用next()方法传入的值为4,他会被赋值给变量first,函数继续执行
function *createIter(){
    let first = yield 1;
    let second = yield first + 2;
    yield second + 3;
}
let iter = createIter();
print(iter.next());
print(iter.next(4));
print(iter.next(5));
print(iter.next());

//yield语句也可以抛出异常
function *createIter(){
    let first = yield 1;
    let second;
    try{
        second = yield first + 2;
    }catch(ex){
        second = 6;
    }
    yield second +3;
}
let iter = createIter();
print(iter.next())   // { value: 1, done: false }
print(iter.next(4)) // { value: 6, done: false }
print(iter.throw(new Error("Boom!")))  //{ value: 9, done: false }
print(iter.next()) //{ value: undefined, done: true }

// yield  遇到 return 也会提前返回

// 在某些情况下,需要两个迭代器合二为一,这时可以创建一个生成器,再给yield语句添加一个星号,就可以将生成数据的过程委托给其他生成器.
function *createNumber(){
    yield 1;
    yield 2;
}
function *createColor(){
    yield "red";
    yield "green";
}
function *createCombinIter(){
    yield *createNumber();
    yield *createColor();
    yield true;
}
var iter = createCombinIter();
print(iter.next()) //{ value: 1, done: false }
print(iter.next()) //{ value: 2, done: false }
print(iter.next())//{ value: 'red', done: false }
print(iter.next())//{ value: 'green', done: false }
print(iter.next())//{ value: true, done: false }
print(iter.next())//{ value: undefined, done: true }

//简单任务执行器: 由于执行yield语句会暂停当前函数的执行过程并等待下一次调用next()方法,因此可以创建一个函数,在函数中调用生成器生成相应的迭代器,从而在不用回调函数的基础上实现异步调用next方法

function run(taskDef){
    //创建一个无使用限制的迭代器
    let task = taskDef();
    let result = task.next();
    //循环调用next函数
    function step(){
        //如果任务没完成,则继续完成
        if(!result.done){
            result = task.next()
            step()
        }
    }
    //开始迭代
    step();
}
run(function*(){
    print("1...");
    yield;
    print("2 ...");
    yield;
    print("3 ... ");
});

//任务执行器之间互相通信
function run(taskDef){
    //创建一个无使用限制的迭代器
    let task = taskDef();
    let result = task.next();
    //循环调用next函数
    function step(){
        //如果任务没完成,则继续完成
        if(!result.done){
            result = task.next(result.value)
            step()
        }
    }
    //开始迭代
    step();
}
run(function*(){
    let value = yield 1;
    print("value: "+value); // 1
    value = yield value + 3
    print("value: "+value) // 4

//如果result.value是一个函数
function run(taskDef){
    //创建一个无使用限制的迭代器
    let task = taskDef();
    let result = task.next();
    //循环调用next函数
    function step(){
        //如果任务没完成,则继续完成
        if(!result.done){
            if(typeof result.value == "function"){
                result.value(function(err,data){
                    if(err){
                        result = task.throw(err);
                        return;
                    }
                    result = task.next(data);
                    step();
                })
            }else{
                result = task.next(result.value);
                step();
            }
        }
    }
    //开始迭代
    step();
}
let fs = require("fs");
function readFile(filename){
    return function(callback){
        fs.readFile(filename,callback);
    };
}

run(function*(){
   let contents = yield readFile("data.txt");
   print(String(contents));
   print("Done");

});

时间: 2024-12-01 06:01:13

js基础的相关文章

7个JS基础知识总结

 这篇文章主要介绍了7个JS基础知识,需要的朋友可以参考下 1.如何在一个对象上添加属性?  方法一:var b = {}; b["name"] = "test"; delete b.name 删除对象的属性 方法二:b.name ="test"; 2.如何判断一个变量是否声明? typeof(a) =="undefined" typeof(d) =="function" 是否为函数   3.怎么表示为字符

JS基础教程——正则表达式示例(推荐)

正则表达式的() [] {}有不同的意思. () 是为了提取匹配的字符串.表达式中有几个()就有几个相应的匹配字符串. (\s*)表示连续空格的字符串. []是定义匹配的字符范围.比如 [a-zA-Z0-9] 表示相应位置的字符要匹配英文字符和数字.[\s*]表示空格或者*号. {}一般用来表示匹配的长度,比如 \s{3} 表示匹配三个空格,\s[1,3]表示匹配一到三个空格. (0-9) 匹配 '0-9′ 本身. [0-9]* 匹配数字(注意后面有 *,可以为空)[0-9]+ 匹配数字(注意后

JS基础系列之正则表达式_正则表达式

正则表达式是一个很牛逼的东东,今天在这里只是简单的给刚刚接触JS的人普及一下,里面若有争议的地方欢迎大家留言! 1.1 什么是正则表达式 ​ 正则表达式(regular expression)是一个描述字符模式的对象,ECMAScript的RegExp 类表示正则表达式,而String和RegExp都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数. ​ 正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具. 1.2 正则表达式的作用 ​ 正则表达式主要用来验证

js基础知识(公有方法、私有方法、特权方法)_基础知识

本文涉及的主题虽然很基础,在许多人看来属于小伎俩,但在JavaScript基础知识中属于一个综合性的话题.这里会涉及到对象属性的封装.原型.构造函数.闭包以及立即执行表达式等知识. 公有方法 公有方法就是能被外部访问并调用的方法. // 在对象中 var Restaurant = { name: 'McDonald', // 公有方法 getName: function() { return this.name; } } // 在构造函数中 function Person(name, age)

js基础之DOM中document对象的常用属性方法详解_javascript技巧

-----引入 每个载入浏览器的 HTML 文档都会成为 Document 对象. Document 对象使我们可以从脚本中对 HTML 页面中的所有元素进行访问. 属性 1  document.anchors  返回对文档中所有 Anchor 对象的引用.还有document.links/document.forms/document.images等 2  document.URL       返回当前文档的url 3  document.title       返回当前文档的标题 4  do

js基础之DOM中元素对象的属性方法详解_javascript技巧

在 HTML DOM (文档对象模型)中,每个部分都是节点. 节点是DOM结构中最基本的组成单元,每一个HTML标签都是DOM结构的节点. 文档是一个    文档节点 . 所有的HTML元素都是    元素节点 所有 HTML 属性都是    属性节点 文本插入到 HTML 元素是    文本节点 注释是    注释节点. 最基本的节点类型是Node类型,其他所有类型都继承自Node,DOM操作往往是js中开销最大的部分,因而NodeList导致的问题最多.要注意:NodeList是'动态的',

最细致的vue.js基础语法 值得收藏!_javascript技巧

介绍 前段时间接触到一个库叫做Vue.js, 个人感觉很棒,所以整理了一篇博文做个介绍. Vue读音/vju:/,和view类似.是一个数据驱动的web界面库.Vue.js只聚焦于视图层,可以很容易的和其他库整合.代码压缩后只有24kb. 可以去 这里下载 .自己整理了一个Vue.js的demo, https://github.com/chenhao-ch/demo-vue 快速入门以下代码是Vue.js最简单的例子, 当input中的内容变化时,p节点的内容会跟着变化. <!-- html -

node.js基础模块http、网页分析工具cherrio实现爬虫_node.js

一.前言       说是爬虫初探,其实并没有用到爬虫相关第三方类库,主要用了node.js基础模块http.网页分析工具cherrio. 使用http直接获取url路径对应网页资源,然后使用cherrio分析. 这里我主要学习过的案例自己敲了一遍,加深理解.在coding的过程中,我第一次把jq获取后的对象直接用forEach遍历,直接报错,是因为jq没有对应的这个方法,只有js数组可以调用. 二.知识点     ①:superagent抓去网页工具.我暂时未用到.     ②:cherrio

JS基础随笔(菜鸟必看篇)_基础知识

在学习的过程中总会一次次的冒出以前囫囵吞枣的地方,下面将今天学到的一下知识点记录下来方便以后查看. JavaScript中的数据类型 简单(基本)数据类型:Number.String.Boolean.Undefined.Null 复杂(引用)数据类型: Object.Array.Date.function等 下面介绍一下简单(基本)数据类型和复杂(引用)数据类型的区别: 简单数据类型:在栈内直接存储值,如下图所示                                          

JS基础系列之正则表达式

正则表达式是一个很牛逼的东东,今天在这里只是简单的给刚刚接触JS的人普及一下,里面若有争议的地方欢迎大家留言! 1.1 什么是正则表达式 ​ 正则表达式(regular expression)是一个描述字符模式的对象,ECMAScript的RegExp 类表示正则表达式,而String和RegExp都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数. ​ 正则表达式用于对字符串模式匹配及检索替换,是对字符串执行模式匹配的强大工具. 1.2 正则表达式的作用 ​ 正则表达式主要用来验证